diff --git a/source/+bruker/brukerreader.p b/source/+bruker/brukerreader.p index b59535f..7daf731 100644 Binary files a/source/+bruker/brukerreader.p and b/source/+bruker/brukerreader.p differ diff --git a/source/+corelab/corelab.fig b/source/+corelab/corelab.fig index cb5d91b..5816ff9 100644 Binary files a/source/+corelab/corelab.fig and b/source/+corelab/corelab.fig differ diff --git a/source/+corelab/corelab.p b/source/+corelab/corelab.p index f03f9a6..cf03752 100644 Binary files a/source/+corelab/corelab.p and b/source/+corelab/corelab.p differ diff --git a/source/+ct/CTBoneSegmentation.p b/source/+ct/CTBoneSegmentation.p deleted file mode 100644 index 46d91be..0000000 Binary files a/source/+ct/CTBoneSegmentation.p and /dev/null differ diff --git a/source/+ct/CTLVSegmentation.p b/source/+ct/CTLVSegmentation.p index e563869..42efbd5 100644 Binary files a/source/+ct/CTLVSegmentation.p and b/source/+ct/CTLVSegmentation.p differ diff --git a/source/+ct/CTWholeHeartSegmentation.p b/source/+ct/CTWholeHeartSegmentation.p deleted file mode 100644 index 6e279ae..0000000 Binary files a/source/+ct/CTWholeHeartSegmentation.p and /dev/null differ diff --git a/source/+ct/WholeHeartCT.oldprototype b/source/+ct/WholeHeartCT.oldprototype deleted file mode 100644 index 1cd445c..0000000 Binary files a/source/+ct/WholeHeartCT.oldprototype and /dev/null differ diff --git a/source/+ct/WholeHeartIntensityMap.mat b/source/+ct/WholeHeartIntensityMap.mat deleted file mode 100644 index 1a3d3ff..0000000 Binary files a/source/+ct/WholeHeartIntensityMap.mat and /dev/null differ diff --git a/source/+ct/autogeneratesax.p b/source/+ct/autogeneratesax.p new file mode 100644 index 0000000..06e5e99 Binary files /dev/null and b/source/+ct/autogeneratesax.p differ diff --git a/source/+ct/coronaryOstiaSearch.p b/source/+ct/coronaryOstiaSearch.p deleted file mode 100644 index 516441e..0000000 Binary files a/source/+ct/coronaryOstiaSearch.p and /dev/null differ diff --git a/source/+ct/ctautocontrast.m b/source/+ct/ctautocontrast.m index 35ae14a..913bc03 100644 --- a/source/+ct/ctautocontrast.m +++ b/source/+ct/ctautocontrast.m @@ -20,8 +20,6 @@ function autocontrastcardiac(no) global SET NO DATA -set(DATA.Handles.autocontrasticon,'state','off'); - if nargin == 0 no = NO; end @@ -116,7 +114,12 @@ function autocontrastcardiac(no) SET(no).IntensityMapping.Brightness=brightness; %update image -drawfunctions('drawcontrastimage',no); +for p = find(DATA.ViewPanels==no) + DATA.ViewIM{p} = []; + drawfunctions('drawimages',p) + createfunctions('addcolorbar',p) +end + myworkoff; @@ -128,8 +131,6 @@ function autocontrastcardiac(no) global SET DATA -set(DATA.Handles.autocontrastallicon,'state','off'); - h = mywaitbarstart(length(SET)*2,'Auto contrast in process',0,DATA.GUI.Segment); for no = 1:length(SET) h = mywaitbarupdate(h); diff --git a/source/+ct/ctlicensecheck.p b/source/+ct/ctlicensecheck.p index 39ac5c1..6ea07a6 100644 Binary files a/source/+ct/ctlicensecheck.p and b/source/+ct/ctlicensecheck.p differ diff --git a/source/+ct/ctperfusion.p b/source/+ct/ctperfusion.p index d2df797..727696a 100644 Binary files a/source/+ct/ctperfusion.p and b/source/+ct/ctperfusion.p differ diff --git a/source/+ct/imagestacksct.p b/source/+ct/imagestacksct.p index 7837de8..6028a18 100644 Binary files a/source/+ct/imagestacksct.p and b/source/+ct/imagestacksct.p differ diff --git a/source/+ct/newfischerclassification.mat b/source/+ct/newfischerclassification.mat deleted file mode 100644 index b8373e9..0000000 Binary files a/source/+ct/newfischerclassification.mat and /dev/null differ diff --git a/source/+ct/showSegmentation.fig b/source/+ct/showSegmentation.fig deleted file mode 100644 index 9f2979f..0000000 Binary files a/source/+ct/showSegmentation.fig and /dev/null differ diff --git a/source/+ct/showSegmentation.m b/source/+ct/showSegmentation.m deleted file mode 100644 index 060224c..0000000 --- a/source/+ct/showSegmentation.m +++ /dev/null @@ -1,836 +0,0 @@ -function showSegmentation(call,arg1,arg2) - -global setCell helpVar handles - -if nargin==0 - %open GUI - figName=['+ct' filesep 'showSegmentation.fig']; - fig=openfig(figName,'reuse'); - handles=guihandles(fig); - handles.fig=fig; - - set(fig,'renderer','zbuffer') - - %Set keypress for entire GUI - segment('recursekeypressfcn',handles.fig,@showSegmentationkeypressed); - - helpVar.XSize=setCell{helpVar.showLevel}.size(1); - helpVar.YSize=setCell{helpVar.showLevel}.size(2); - helpVar.ZSize=setCell{helpVar.showLevel}.size(3); - - helpVar.rslice = round(helpVar.ZSize/2); - helpVar.gslice = round(helpVar.YSize/2); - helpVar.bslice = round(helpVar.XSize/2); - - warning('off','MATLAB:contour:ConstantData'); %Ignore warning messages from contour. - - %Install icons - try - load('icons.mat','icon'); - catch - myfailed('Critical error: Could not read icons.'); - return; - end; - - mytoolbar = uitoolbar(handles.fig); - - %Selection icon - props.ClickedCallback = 'ct.showSegmentation(''selecttool'')'; - props.ToolTip = 'Pointer tool.'; - props.CData = icon.selectslices; - props.Tag = 'selecticon'; - props.separator = 'off'; - handles.selecticon = uitoggletool(mytoolbar,props); - - %zoom in icon - props.ClickedCallback = 'ct.showSegmentation(''zoomin'')'; - props.ToolTip = 'Zoom in'; - props.CData = icon.zoomin; - props.Tag = 'zoominicon'; - props.separator = 'off'; - handles.zoominicon = uitoggletool(mytoolbar,props); - - %zoom out icon - props.ClickedCallback = 'ct.showSegmentation(''zoomout'')'; - props.ToolTip = 'Zoom out'; - props.CData = icon.zoomout; - props.Tag = 'zoomouticon'; - props.separator = 'off'; - handles.zoomouticon = uitoggletool(mytoolbar,props); - - %refresh - props.ClickedCallback = 'ct.showSegmentation(''refresh'')'; - props.ToolTip = 'Refresh image'; - props.CData = icon.refresh; - props.Tag = 'refreshicon'; - props.separator = 'on'; - handles.refreshicon = uitoggletool(mytoolbar,props); - - - %set default values - showSegmentationDefault - %set buttons default - ct.showSegmentation('updatebuttons','default'); - %set sliders - ct.showSegmentation('updatesliders'); - %update image - ct.showSegmentation('update'); - -else - switch call - case 'updatebuttons' - switch arg1 - case 'CTWholeHeartSegmentation' - set(handles.wholeheartpushbutton,'visible', 'on', 'enable', 'on'); - set(handles.coronaryostiapushbutton,'visible','off','enable', 'off'); - set(handles.bonesegmentationpushbutton,'visible','off','enable','off'); - set(handles.runoffpushbutton,'visible','off','enable','off'); - set(handles.carotidrenalpushbutton,'visible','off','enable','off'); - set(handles.bonethreshslider,'visible','off','enable','off'); - set(handles.bonethreshtext,'visible','off'); - case 'coronaryOstiaSearch' - switch arg2 - case 'init' - set(handles.wholeheartpushbutton,'visible', 'on', 'enable', 'off'); - set(handles.coronaryostiapushbutton,'visible','on','enable', 'off'); - case 'segmentation done' - set(handles.wholeheartpushbutton,'visible', 'on', 'enable', 'on'); - set(handles.coronaryostiapushbutton,'visible','on','enable', 'on'); - end - set(handles.bonesegmentationpushbutton,'visible','off','enable','off'); - set(handles.runoffpushbutton,'visible','off','enable','off'); - set(handles.carotidrenalpushbutton,'visible','off','enable','off'); - set(handles.bonethreshslider,'visible','off','enable','off'); - set(handles.bonethreshtext,'visible','off'); - case 'CTBoneSegmentation' - set(handles.wholeheartpushbutton,'visible', 'off', 'enable', 'off'); - set(handles.coronaryostiapushbutton,'visible','off','enable', 'off'); - set(handles.bonesegmentationpushbutton,'visible','on','enable','on'); - set(handles.runoffpushbutton,'visible','off','enable','off'); - set(handles.carotidrenalpushbutton,'visible','off','enable','off'); - set(handles.bonethreshslider,'visible','on','enable','on'); - set(handles.bonethreshtext,'visible','on'); - set(handles.bonethreshslider,'min',-0.5,'max',1.5,'value',0.5,... - 'sliderstep',[0.05 0.1]); - case 'CTARunOff' - set(handles.wholeheartpushbutton,'visible', 'off', 'enable', 'off'); - set(handles.coronaryostiapushbutton,'visible','off','enable', 'off'); - set(handles.bonesegmentationpushbutton,'visible','off','enable','off'); - set(handles.runoffpushbutton,'visible','on','enable','on'); - set(handles.carotidrenalpushbutton,'visible','off','enable','off'); - set(handles.bonethreshslider,'visible','off','enable','off'); - set(handles.bonethreshtext,'visible','off'); - case 'CTACarotidRenal' - set(handles.wholeheartpushbutton,'visible', 'off', 'enable', 'off'); - set(handles.coronaryostiapushbutton,'visible','off','enable', 'off'); - set(handles.bonesegmentationpushbutton,'visible','off','enable','off'); - set(handles.runoffpushbutton,'visible','off','enable','off'); - set(handles.carotidrenalpushbutton,'visible','on','enable','on'); - set(handles.bonethreshslider,'visible','off','enable','off'); - set(handles.bonethreshtext,'visible','off'); - case 'default' - ct.showSegmentation('updatebuttons','CTWholeHeartSegmentation'); - otherwise - set(handles.wholeheartpushbutton,'visible', 'on', 'enable', 'off'); - set(handles.coronaryostiapushbutton,'visible','on','enable', 'off'); - set(handles.bonesegmentationpushbutton,'visible','on','enable','off'); - set(handles.runoffpushbutton,'visible','on','enable','off'); - set(handles.carotidrenalpushbutton,'visible','on','enable','off'); - set(handles.bonethreshslider,'visible','off','enable','off'); - set(handles.bonethreshtext,'visible','off'); - end - case 'updatesliders' - set(handles.rslider,'min',1,'max',helpVar.ZSize,'value',helpVar.ZSize-helpVar.rslice+1,... - 'sliderstep',[1/helpVar.ZSize 3/helpVar.ZSize]); - set(handles.gslider,'min',1,'max',helpVar.YSize,'value',helpVar.gslice,... - 'sliderstep',[1/helpVar.YSize 3/helpVar.YSize]); - set(handles.bslider,'min',1,'max',helpVar.XSize,'value',helpVar.bslice,... - 'sliderstep',[1/helpVar.XSize 3/helpVar.XSize]); - case 'slice' - switch arg1 - case 'r' - helpVar.rslice = max(min(helpVar.rslice-arg2,helpVar.ZSize),1); - case 'g' - helpVar.gslice = max(min(helpVar.gslice+arg2,helpVar.YSize),1); - case 'b' - helpVar.bslice = max(min(helpVar.bslice+arg2,helpVar.XSize),1); - end; - ct.showSegmentation('update'); - case 'rslider' - helpVar.rslice = 1+helpVar.ZSize-min(helpVar.ZSize,max(round(mygetslider(handles.rslider)),1)); - set(handles.rslider,'Value',helpVar.ZSize-helpVar.rslice+1); - ct.showSegmentation('rdraw'); - ct.showSegmentation('sdraw'); - ct.showSegmentation('lineupdate'); - case 'gslider' - helpVar.gslice = min(helpVar.YSize,max(round(mygetslider(handles.gslider)),1)); - set(handles.gslider,'Value',helpVar.gslice); - ct.showSegmentation('gdraw'); - ct.showSegmentation('lineupdate'); - case 'bslider' - helpVar.bslice = min(helpVar.XSize,max(round(mygetslider(handles.bslider)),1)); - set(handles.bslider,'Value',helpVar.bslice); - ct.showSegmentation('bdraw'); - ct.showSegmentation('lineupdate'); - case 'bonethreshslider' - thresh=mygetslider(handles.bonethreshslider); - ct.CTBoneSegmentation('adjustthreshhold',thresh); - case 'overviewzoom' - figure(12); - handles.overviewaxes = gca; - ct.showSegmentation('update'); - ct.showSegmentation('isosurface'); - axis off image; - cameratoolbar(12); - case 'isosurface' - if isempty(setCell{helpVar.showLevel}.segmentation) - myfailed('No segmentation exists'); - return; - end - fv = isosurface(double(... - setCell{helpVar.showLevel}.segmentation),... - 0.5); - - if get(handles.reducecheckbox,'value') - fv = reducepatch(fv,0.2); - end; - - %Flip in z-direction and xy - fv.vertices(:,3) = (helpVar.ZSize+1)-fv.vertices(:,3); - temp = fv.vertices(:,2); - fv.vertices(:,2) = fv.vertices(:,1); - fv.vertices(:,1) = temp; - - %--- Display - hold(handles.overviewaxes,'on'); - h = patch(fv,'parent',handles.overviewaxes); - hold(handles.overviewaxes,'off'); - set(h,'facecolor',[1 0 0],'edgecolor',[1 1 0],'facealpha',0.5); - if not(get(handles.polygonscheckbox,'value')) - set(h,'edgealpha',0); - end; - case 'update' - ct.showSegmentation('rdraw'); - ct.showSegmentation('gdraw'); - ct.showSegmentation('bdraw'); - - ct.showSegmentation('lineupdate'); - ct.showSegmentation('updatesliders'); - case 'selection' - helpVar.ViewSelection = get(handles.selectioncheckbox,'value'); - ct.showSegmentation('update'); - case 'outline' - helpVar.ViewOutline = get(handles.outlinecheckbox,'value'); - ct.showSegmentation('update'); - case 'mip' - helpVar.ViewMIP = get(handles.mipcheckbox,'value'); - ct.showSegmentation('update'); - case 'lineupdate' - set(handles.grline,'ydata',[helpVar.rslice helpVar.rslice]); - set(handles.brline,'ydata',[helpVar.rslice helpVar.rslice]); - - set(handles.rgline,'xdata',[helpVar.gslice helpVar.gslice]); - set(handles.bgline,'xdata',[helpVar.gslice helpVar.gslice]); - - set(handles.rbline,'ydata',[helpVar.bslice helpVar.bslice]); - set(handles.gbline,'xdata',[helpVar.bslice helpVar.bslice]); - case 'rdraw' - %--- Red image - handles.rimage = image(squeeze(setCell{helpVar.showLevel}.IM(:,:,helpVar.rslice)),'parent',handles.raxes); - - %Add objects - hold(handles.raxes,'on'); - handles.rbline = plot(handles.raxes,[0 helpVar.YSize],[helpVar.bslice helpVar.bslice],'b-'); - handles.rgline = plot(handles.raxes,[helpVar.gslice helpVar.gslice],[0 helpVar.XSize],'g-'); - x1 = helpVar.RZoomState(1)+0.5; - x2 = helpVar.RZoomState(2)-0.5; - y1 = helpVar.RZoomState(3)+0.5; - y2 = helpVar.RZoomState(4)-0.5; - handles.rimagebox = plot(handles.raxes,[x1 x2 x2 x1 x1],[y1 y1 y2 y2 y1],'r-'); - set(handles.rimagebox,'linewidth',2); - - if ~isempty(setCell{helpVar.showLevel}.segmentation) - [c,h] = contour(... - handles.raxes,... - double(squeeze(setCell{helpVar.showLevel}.segmentation(:,:,helpVar.rslice))),... - [0.5 0.5]); - set(h,'ButtonDownFcn','ct.showSegmentation(''click'',''r'')'); - children = get(h,'children'); - set(children,'edgecolor',[1 1 0]); - if helpVar.ViewOutline - set(children,'visible','on'); - else - set(children,'visible','off'); - end; - end - - - %show landmarks - if ~isempty(setCell{helpVar.showLevel}.landmarks.X) - for loop=1:length(setCell{helpVar.showLevel}.landmarks.X) - if round(setCell{helpVar.showLevel}.landmarks.Z(loop))==helpVar.rslice - handles.pointp(loop) = plot(handles.raxes,... - setCell{helpVar.showLevel}.landmarks.Y(loop),setCell{helpVar.showLevel}.landmarks.X(loop),'w+'); - handles.pointo(loop) = plot(handles.raxes,... - setCell{helpVar.showLevel}.landmarks.Y(loop),setCell{helpVar.showLevel}.landmarks.X(loop),'wo'); - handles.pointtext(loop) = text(... - 'position',[setCell{helpVar.showLevel}.landmarks.Y(loop)+2 setCell{helpVar.showLevel}.landmarks.X(loop)],... - 'string',setCell{helpVar.showLevel}.landmarks.Label{loop},... - 'parent',handles.raxes,... - 'color',[1 1 1]); - end - end - end - - hold(handles.raxes,'off'); - - %Aspect ratio - axis(handles.raxes,'off'); - set(handles.raxes,'Clim',[0 1],'dataaspectratio',... - [1/setCell{helpVar.showLevel}.resolution(2) ... - 1/setCell{helpVar.showLevel}.resolution(1) 1]); - - set(handles.rimage,'ButtonDownFcn','ct.showSegmentation(''click'',''r'')'); - set([handles.rbline handles.rgline],'ButtonDownFcn','ct.showSegmentation(''click'',''r'')'); - ct.showSegmentation('rupdate'); - - case 'gdraw' - %--- Green image - temp = squeeze(setCell{helpVar.showLevel}.IM(:,helpVar.gslice,:))'; - handles.gimage = image(temp,'parent',handles.gaxes); - - %Add objects - hold(handles.gaxes,'on'); - - handles.grline = plot(handles.gaxes,[0 helpVar.YSize],[helpVar.rslice helpVar.rslice],'r-'); - handles.gbline = plot(handles.gaxes,[helpVar.bslice helpVar.bslice],[0 helpVar.ZSize],'b-'); - - x1 = helpVar.GZoomState(1)+0.5; - x2 = helpVar.GZoomState(2)-0.5; - y1 = helpVar.GZoomState(3)+0.5; - y2 = helpVar.GZoomState(4)-0.5; - handles.gimagebox = plot(handles.gaxes,[x1 x2 x2 x1 x1],[y1 y1 y2 y2 y1],'g-'); - set(handles.gimagebox,'linewidth',2); - - set(handles.gaxes,'Clim',[0 1],'dataaspectratio',... - [1/setCell{helpVar.showLevel}.resolution(2) ... - 1/setCell{helpVar.showLevel}.resolution(3) 1]); - - if ~isempty(setCell{helpVar.showLevel}.segmentation) - %show segmentation - [c,h] = contour(... - handles.gaxes,... - double(squeeze(setCell{helpVar.showLevel}.segmentation(:,helpVar.gslice,:)))',... - [0.5 0.5]); - set(h,'ButtonDownFcn','ct.showSegmentation(''click'',''g'')'); - children = get(h,'children'); - set(children,'edgecolor',[1 1 0]); - if helpVar.ViewOutline - set(children,'visible','on'); - else - set(children,'visible','off'); - end; - end - - - %show landmarks - if ~isempty(setCell{helpVar.showLevel}.landmarks.X) - for loop=1:length(setCell{helpVar.showLevel}.landmarks.X) - if round(setCell{helpVar.showLevel}.landmarks.Y(loop))==helpVar.gslice - handles.pointp(loop) = plot(handles.gaxes,... - setCell{helpVar.showLevel}.landmarks.X(loop),setCell{helpVar.showLevel}.landmarks.Z(loop),'w+'); - handles.pointo(loop) = plot(handles.gaxes,... - setCell{helpVar.showLevel}.landmarks.X(loop),setCell{helpVar.showLevel}.landmarks.Z(loop),'wo'); - handles.pointtext(loop) = text(... - 'position',[setCell{helpVar.showLevel}.landmarks.X(loop)+2 setCell{helpVar.showLevel}.landmarks.Z(loop)],... - 'string',setCell{helpVar.showLevel}.landmarks.Label{loop},... - 'parent',handles.gaxes,... - 'color',[1 1 1]); - end - end - end - - hold(handles.gaxes,'off'); - axis(handles.gaxes,'off'); - set(handles.gimage,'ButtonDownFcn','ct.showSegmentation(''click'',''g'')'); - set([handles.grline handles.gbline],'ButtonDownFcn','ct.showSegmentation(''click'',''g'')'); - - set(handles.gaxes,'Clim',[0 1],'dataaspectratio',... - [1/setCell{helpVar.showLevel}.resolution(2) ... - 1/setCell{helpVar.showLevel}.resolution(3) 1]); - ct.showSegmentation('gupdate'); - case 'bdraw' - - %--- Blue image - temp = squeeze(setCell{helpVar.showLevel}.IM(helpVar.bslice,:,:))'; - handles.bimage = image(temp,'parent',handles.baxes); - - %Add objects - hold(handles.baxes,'on'); - handles.brline = plot(handles.baxes,[0 helpVar.XSize],[helpVar.rslice helpVar.rslice],'r-'); - handles.bgline = plot(handles.baxes,[helpVar.gslice helpVar.gslice],[0 helpVar.ZSize],'g-'); - x1 = helpVar.BZoomState(1)+0.5; - x2 = helpVar.BZoomState(2)-0.5; - y1 = helpVar.BZoomState(3)+0.5; - y2 = helpVar.BZoomState(4)-0.5; - handles.bimagebox = plot(handles.baxes,[x1 x2 x2 x1 x1],[y1 y1 y2 y2 y1],'b-'); - set(handles.bimagebox,'linewidth',2); - - %Add objects - hold(handles.raxes,'on'); - handles.rbline = plot(handles.raxes,[0 helpVar.YSize],[helpVar.bslice helpVar.bslice],'b-'); - handles.rgline = plot(handles.raxes,[helpVar.gslice helpVar.gslice],[0 helpVar.XSize],'g-'); - x1 = helpVar.RZoomState(1)+0.5; - x2 = helpVar.RZoomState(2)-0.5; - y1 = helpVar.RZoomState(3)+0.5; - y2 = helpVar.RZoomState(4)-0.5; - handles.rimagebox = plot(handles.raxes,[x1 x2 x2 x1 x1],[y1 y1 y2 y2 y1],'r-'); - set(handles.rimagebox,'linewidth',2); - - %show segmentation - if ~isempty(setCell{helpVar.showLevel}.segmentation) - [c,h] = contour(... - handles.baxes,... - double(squeeze(setCell{helpVar.showLevel}.segmentation(helpVar.bslice,:,:)))',... - [0.5 0.5]); - set(h,'ButtonDownFcn','ct.showSegmentation(''click'',''b'')'); - children = get(h,'children'); - set(children,'edgecolor',[1 1 0]); - if helpVar.ViewOutline - set(children,'visible','on'); - else - set(children,'visible','off'); - end; - end - - %show landmarks - if ~isempty(setCell{helpVar.showLevel}.landmarks.X) - for loop=1:length(setCell{helpVar.showLevel}.landmarks.X) - if round(setCell{helpVar.showLevel}.landmarks.X(loop))==helpVar.bslice - handles.pointp(loop) = plot(handles.baxes,... - setCell{helpVar.showLevel}.landmarks.Y(loop),setCell{helpVar.showLevel}.landmarks.Z(loop),'w+'); - handles.pointo(loop) = plot(handles.baxes,... - setCell{helpVar.showLevel}.landmarks.Y(loop),setCell{helpVar.showLevel}.landmarks.Z(loop),'wo'); - handles.pointtext(loop) = text(... - 'position',[setCell{helpVar.showLevel}.landmarks.Y(loop)+2 setCell{helpVar.showLevel}.landmarks.Z(loop)],... - 'string',setCell{helpVar.showLevel}.landmarks.Label{loop},... - 'parent',handles.baxes,... - 'color',[1 1 1]); - end - end - end - - hold(handles.baxes,'off'); - axis(handles.baxes,'off'); - set(handles.bimage,'ButtonDownFcn','ct.showSegmentation(''click'',''b'')'); - set([handles.brline handles.bgline],'ButtonDownFcn','ct.showSegmentation(''click'',''b'')'); - - set(handles.baxes,'Clim',[0 1],'dataaspectratio',... - [1/setCell{helpVar.showLevel}.resolution(1) ... - 1/setCell{helpVar.showLevel}.resolution(3) 1]); - ct.showSegmentation('bupdate'); - - case 'rupdate' - %--- Update 'red' image - if helpVar.ViewMIP - %MIP - temp = squeeze(max(setCell{helpVar.showLevel}.IM,[],3)); - if ~isempty(setCell{helpVar.showLevel}.segmentation) - overlaySegmentation = squeeze(max(setCell{helpVar.showLevel}.segmentation,[],3))>0.5; - else - overlaySegmentation=[]; - end - else - %Slice - temp = squeeze(setCell{helpVar.showLevel}.IM(:,:,helpVar.rslice)); - if ~isempty(setCell{helpVar.showLevel}.segmentation) - overlaySegmentation = squeeze(setCell{helpVar.showLevel}.segmentation(:,:,helpVar.rslice))>0.5; - else - overlaySegmentation=[]; - end - end; - %Update image - - set(handles.rimage,'cdata',... - remapandoverlaySegmentation(temp,overlaySegmentation)); - - %zoom state - if isempty(helpVar.RZoomState) - helpVar.RZoomState = [0.5;size(temp,2)-0.5;0.5;size(temp,1)-0.5]; - end; - set(handles.raxes,... - 'xlim',helpVar.RZoomState(1:2),... - 'ylim',helpVar.RZoomState(3:4)); - - x1 = helpVar.RZoomState(1); - x2 = helpVar.RZoomState(2); - y1 = helpVar.RZoomState(3); - y2 = helpVar.RZoomState(4); - set(handles.rimagebox,'xdata',[x1 x2 x2 x1 x1],'ydata',[y1 y1 y2 y2 y1]); - - case 'gupdate' - %--- Green image - if helpVar.ViewMIP - %MIP - temp = squeeze(max(setCell{helpVar.showLevel}.IM,[],2))'; - if ~isempty(setCell{helpVar.showLevel}.segmentation) - overlaySegmentation = squeeze(max(setCell{helpVar.showLevel}.segmentation,[],2))'>0.5; - else - overlaySegmentation=[]; - end - else - %Slice - temp = squeeze(setCell{helpVar.showLevel}.IM(:,helpVar.gslice,:))'; - if ~isempty(setCell{helpVar.showLevel}.segmentation) - overlaySegmentation = squeeze(setCell{helpVar.showLevel}.segmentation(:,helpVar.gslice,:))'>0.5; - else - overlaySegmentation=[]; - end - end; - %Update image - set(handles.gimage,'cdata',... - remapandoverlaySegmentation(temp,overlaySegmentation)); - - %zoom state - if isempty(helpVar.GZoomState) - helpVar.GZoomState = [0.5;size(temp,2)-0.5;0.5;size(temp,1)-0.5]; - end; - set(handles.gaxes,... - 'xlim',helpVar.GZoomState(1:2),... - 'ylim',helpVar.GZoomState(3:4)); - - x1 = helpVar.GZoomState(1); - x2 = helpVar.GZoomState(2); - y1 = helpVar.GZoomState(3); - y2 = helpVar.GZoomState(4); - set(handles.gimagebox,'xdata',[x1 x2 x2 x1 x1],'ydata',[y1 y1 y2 y2 y1]); - - case 'bupdate' - if helpVar.ViewMIP - %MIP - temp = squeeze(max(setCell{helpVar.showLevel}.IM,[],1))'; - if ~isempty(setCell{helpVar.showLevel}.segmentation) - overlaySegmentation = squeeze(max(setCell{helpVar.showLevel}.segmentation,[],1))'>0.5; - else - overlaySegmentation=[]; - end - else - %Slice - temp = squeeze(setCell{helpVar.showLevel}.IM(helpVar.bslice,:,:))'; - if ~isempty(setCell{helpVar.showLevel}.segmentation) - overlaySegmentation = squeeze(setCell{helpVar.showLevel}.segmentation(helpVar.bslice,:,:))'>0.5; - else - overlaySegmentation=[]; - end - end; - %Update image - set(handles.bimage,'cdata',... - remapandoverlaySegmentation(temp,overlaySegmentation)); - %zoom state - if isempty(helpVar.BZoomState) - helpVar.BZoomState = [0.5;size(temp,2)-0.5;0.5;size(temp,1)-0.5]; - end; - set(handles.baxes,... - 'xlim',helpVar.BZoomState(1:2),... - 'ylim',helpVar.BZoomState(3:4)); - - x1 = helpVar.BZoomState(1); - x2 = helpVar.BZoomState(2); - y1 = helpVar.BZoomState(3); - y2 = helpVar.BZoomState(4); - set(handles.bimagebox,'xdata',[x1 x2 x2 x1 x1],'ydata',[y1 y1 y2 y2 y1]); - - case 'volume' - if isempty(setCell{helpVar.showLevel}.segmentation) - myfailed('No segmentation exists'); - return - end - num=sum(sum(sum(setCell{helpVar.showLevel}.segmentation>0.5))); - voxel = cumprod(setCell{helpVar.showLevel}.resolution); - num = num*voxel(end); - num = num/1000; %convert to ml == cm^3 - - msgbox(dprintf('Totalvolume of object is %0.5g [ml]',num)); - case 'zoomin' - set(handles.zoominicon,'state','off'); - helpVar.Zoom = helpVar.Zoom*1.2; - helpVar.RZoomState = zoomhelper(helpVar.RZoomState,1.2,... - [helpVar.YSize helpVar.XSize]); - helpVar.GZoomState = zoomhelper(helpVar.GZoomState,1.2,... - [helpVar.XSize helpVar.ZSize]); - helpVar.BZoomState = zoomhelper(helpVar.BZoomState,1.2,... - [helpVar.YSize helpVar.ZSize]); - - ct.showSegmentation('rupdate'); - ct.showSegmentation('gupdate'); - ct.showSegmentation('bupdate'); - case 'zoomout' - set(handles.zoomouticon,'state','off'); - helpVar.Zoom = helpVar.Zoom/1.2; - helpVar.Zoom = helpVar.Zoom*1.2; - helpVar.RZoomState = zoomhelper(helpVar.RZoomState,1/1.2,[helpVar.YSize helpVar.XSize]); - helpVar.GZoomState = zoomhelper(helpVar.GZoomState,1/1.2,[helpVar.XSize helpVar.ZSize]); - helpVar.BZoomState = zoomhelper(helpVar.BZoomState,1/1.2,[helpVar.YSize helpVar.ZSize]); - - ct.showSegmentation('rupdate'); - ct.showSegmentation('gupdate'); - ct.showSegmentation('bupdate'); - case 'selecttool' - helpVar.CurrentTool = 'select'; - ct.showSegmentation('update'); - case 'click' - %Called when mouse pressed - [x,y] = mygetcurrentpoint(gca); - - type = get(gcf,'SelectionType'); - switch helpVar.CurrentTool - case 'select' - %--- Selection tool - switch type - case 'normal' - %Mark pen/window - helpVar.pencolor = arg1; - selectmotion; %Call once to update - - %Start selection tool if kept down - set(gcf,'WindowButtonMotionFcn','ct.showSegmentation(''selectmotion'')'); - set(gcf,'WindowButtonUpFcn','ct.showSegmentation(''selectbuttonup'')'); - case 'extend' - %Start paning tool - helpVar.pencolor = arg1; - set(gcf,'WindowButtonMotionFcn','ct.showSegmentation(''panmotion'')'); - set(gcf,'WindowButtonUpFcn','ct.showSegmentation(''panbuttonup'')'); - end; - - end; %switch clause - case 'refresh' - set(handles.refreshicon,'state','off'); - helpVar.RZoomState = [0.5 helpVar.XSize-0.5 0.5 helpVar.YSize-0.5]; - helpVar.GZoomState = [0.5 helpVar.YSize-0.5 0.5 helpVar.ZSize-0.5]; - helpVar.BZoomState = [0.5 helpVar.XSize-0.5 0.5 helpVar.ZSize-0.5]; - helpVar.LevelSet.Zoom = 1; - ct.showSegmentation('update'); - end -end - -%--------------------------------------- -function showSegmentationkeypressed(fignum,evnt) -%--------------------------------------- -global setCell helpVar - -key = getkey(evnt); - -switch key - case 'z' - %Zoom in (z) - ct.showSegmentation('zoomin'); - case 'x' - %Zoom out (x) - ct.showSegmentation('zoomout'); - case 'uparrow' - switch helpVar.pencolor - case 'r' - ct.showSegmentation('slice','r',1) - case 'g' - ct.showSegmentation('slice','g',1) - case 'b' - ct.showSegmentation('slice','b',1) - end - case 'downarrow' - switch helpVar.pencolor - case 'r' - ct.showSegmentation('slice','r',-1) - case 'g' - ct.showSegmentation('slice','g',-1) - case 'b' - ct.showSegmentation('slice','b',-1) - end -end; - -%------------------------------------------------------------------ -function im = remapandoverlaySegmentation(temp,overlaySegmentation) -%------------------------------------------------------------------ -global setCell helpVar - -%Remap to correct colorscale and add overlay if user wants that. - -%Remap data -if isequal(helpVar.ViewIm,'magnitude') - tempr = calcfunctions('remapuint8',temp); - tempg = tempr; - tempb = tempr; -else - temp = temp/4+0.5; - tempr = segment('remap',temp,helpVar.Colormap(:,1)); - tempg = segment('remap',temp,helpVar.Colormap(:,2)); - tempb = segment('remap',temp,helpVar.Colormap(:,3)); -end; -%Add overlay -if helpVar.ViewSelection - tempr(overlaySegmentation)=1; - %tempg(overlaybw)=0; - %tempb(overlaybw)=0; %red -end; -im = cat(3,tempr,tempg,tempb); - -%------------------------------- -function showSegmentationDefault -%------------------------------- -global helpVar setCell - -helpVar.pencolor = ''; %contains r,g,b depending which window drawing in -helpVar.RZoomState = [0.5 helpVar.XSize-0.5 0.5 helpVar.YSize-0.5]; -helpVar.GZoomState = [0.5 helpVar.YSize-0.5 0.5 helpVar.ZSize-0.5]; -helpVar.BZoomState = [0.5 helpVar.XSize-0.5 0.5 helpVar.ZSize-0.5]; -helpVar.Zoom = 1; -helpVar.CurrentTool = 'select'; -helpVar.ViewIm = 'magnitude'; %can also be speed -helpVar.ViewMIP = false; %view mip image -helpVar.ViewInteraction = true; %View manual interaction -helpVar.ViewSelection = false; %View selection -helpVar.ViewOutline = true; %View outline - -%----------------------------------------------------- -function [zoomstate] = zoomhelper(zoomstate,f,sz) -%----------------------------------------------------- -%imagesize -xsize=sz(1); -ysize=sz(2); -%Get old position -temp = zoomstate; -oldxspan=temp(2)-temp(1); -oldyspan=temp(4)-temp(3); - -xlim = [... - 0.5*(temp(1)+temp(2))-0.5*(temp(2)-temp(1))/f ... - 0.5*(temp(1)+temp(2))+0.5*(temp(2)-temp(1))/f]; -%f = f*0.5; -ylim = [... - 0.5*(temp(3)+temp(4))-0.5*(temp(4)-temp(3))/f ... - 0.5*(temp(3)+temp(4))+0.5*(temp(4)-temp(3))/f]; - -xspan=(xlim(2)-xlim(1)); -yspan=(ylim(2)-ylim(1)); -if f>1 - if xsize>ysize - if xspan>oldyspan - ylim=[0.5 ysize-0.5]; - elseif oldyspan>xspan - ylim=[0.5*(temp(3)+temp(4)) - 0.5*(xlim(2)-xlim(1))... - 0.5*(temp(3)+temp(4)) + 0.5*(xlim(2)-xlim(1))]; - end - else - if yspan>oldxspan - xlim=[0.5 xsize-0.5]; - elseif oldxspan>yspan - xlim=[0.5*(temp(1)+temp(2)) - 0.5*(ylim(2)-ylim(1))... - 0.5*(temp(1)+temp(2)) + 0.5*(ylim(2)-ylim(1))]; - end - end -else - if xsize>ysize - if xspan<=xsize - if oldxspan>yspan || yspan>=ysize - ylim=[0.5 ysize-0.5]; - elseif yspan>oldxspan - ylim=[0.5*(temp(3)+temp(4)) - 0.5*(xlim(2)-xlim(1))... - 0.5*(temp(3)+temp(4)) + 0.5*(xlim(2)-xlim(1))]; - end - end - else - if yspan<=ysize - if oldyspan>xspan ||xspan>=xsize - xlim=[0.5 xsize-0.5]; - elseif xspan>oldyspan - xlim=[0.5*(temp(1)+temp(2)) - 0.5*(ylim(2)-ylim(1))... - 0.5*(temp(1)+temp(2)) + 0.5*(ylim(2)-ylim(1))]; - end - end - end -end - -zoomstate = [xlim(:);ylim(:)]; -%------------------------------ -function selectbuttonup -%------------------------------ - -set(gcf,'WindowButtonMotionFcn',''); -set(gcf,'WindowButtonUpFcn',''); -ct.showSegmentation('update'); - -%---------------------------- -function selectmotion -%---------------------------- -global helpVar -%rewritten to be able to use in timeresolve volumes (JS) - -[x,y] = mygetcurrentpoint(gca); - - -switch helpVar.pencolor - case 'r' - helpVar.gslice = round(x); - helpVar.bslice = round(y); - case 'g' - helpVar.bslice = round(x); - helpVar.rslice = round(y); - case 'b' - helpVar.gslice = round(x); - helpVar.rslice = round(y); -end; - -%Move the line -ct.showSegmentation('update') - - -%--------------------------- -function panbuttonup -%--------------------------- -global helpVar - -test='i panbuttonup' - -set(gcf,'WindowButtonMotionFcn',''); -set(gcf,'WindowButtonUpFcn',''); - -ax = gca; -xlim = get(ax,'xlim'); -ylim = get(ax,'ylim'); - -switch helpVar.pencolor - case 'r' - helpVar.RZoomState = [xlim ylim]; - case 'g' - helpVar.GZoomState = [xlim ylim]; - case 'b' - helpVar.BZoomState = [xlim ylim]; -end; -ct.showSegmentation('update'); -panmotion('reset'); %Reset for next time - -%-------------------------------- -function panmotion(reset) -%-------------------------------- -persistent startpos - -test='i panmotion' - -if nargin==1 - startpos = []; - return; -end; - -%Get mouse position -[p(1),p(2)] = mygetcurrentpoint(gca); - -if isempty(startpos) - startpos = p; -end; - -xlim = get(gca,'xlim'); -ylim = get(gca,'ylim'); -set(gca,... - 'xlim',xlim+startpos(1)-p(1),... - 'ylim',ylim+startpos(2)-p(2)); - - diff --git a/source/+ct/whichstackct.fig b/source/+ct/whichstackct.fig deleted file mode 100644 index 91d1ec7..0000000 Binary files a/source/+ct/whichstackct.fig and /dev/null differ diff --git a/source/+perfusion/perfusion.fig b/source/+perfusion/perfusion.fig index 96cba57..d05df1f 100644 Binary files a/source/+perfusion/perfusion.fig and b/source/+perfusion/perfusion.fig differ diff --git a/source/+perfusion/perfusion.p b/source/+perfusion/perfusion.p index 4192486..4d7d9da 100644 Binary files a/source/+perfusion/perfusion.p and b/source/+perfusion/perfusion.p differ diff --git a/source/+perfusion/perfusionscoring.fig b/source/+perfusion/perfusionscoring.fig index 6706538..8f9cf7f 100644 Binary files a/source/+perfusion/perfusionscoring.fig and b/source/+perfusion/perfusionscoring.fig differ diff --git a/source/+perfusion/perfusionscoring.m b/source/+perfusion/perfusionscoring.m deleted file mode 100644 index 96dfb20..0000000 --- a/source/+perfusion/perfusionscoring.m +++ /dev/null @@ -1,1695 +0,0 @@ -function varargout = perfusionscoring(varargin) -%GUI for fast MR perfusion analysis -macro_helper(varargin{:}); -if nargin == 0 || isempty(varargin{1}) - varargin{1} = 'init'; -end -[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard - -%------------ -function init %#ok -%------------ -%Initiate GUI -global DATA SET - - -% Add no and scoringedit array to mygui properties -allnos = 1:numel(SET); -stressnos = find(strcmp({SET.ImageType},'Perfusion Stress Aligned')); -if isempty(stressnos) - stressnos = find(strcmp({SET.ImageType},'Perfusion Stress')); - hasalignedstress = false; -else - hasalignedstress = true; -end - -restnos = find(strcmp({SET.ImageType},'Perfusion Rest Aligned')); -if isempty(restnos) - restnos = find(strcmp({SET.ImageType},'Perfusion Rest')); - hasalignedrest = false; -else - hasalignedrest = true; -end - -restonly = false; -stressonly = false; -if hasalignedstress && hasalignedrest -elseif hasalignedstress - if yesno(['Found only Perfusion Stress Aligned image stack. Proceed ' ... - 'using only one stack for perfusion analysis?']) - stressonly = true; - else - return - end - - -elseif hasalignedrest - if yesno(['Found only Perfusion Rest Aligned image stack. Proceed ' ... - 'using only one stack for perfusion analysis?']) - %analysed = true; - restonly = true; - %stressnos = restnos; - else - return - end -end - -scarnos = findfunctions('findscarshortaxisno'); - -if (numel(restnos) ~= 1 || numel(stressnos) ~= 1) - if isempty(restnos) && isempty(stressnos) - myfailed(['Could not find either of stress/rest image stacks. Please ' ... - 'set image description of two stacks to Perfusion Stress and ' ... - 'Perfusion Rest before launching Perfusion module']); - return - elseif isempty(restnos) && ~hasalignedstress - if yesno(['Found only Perfusion Stress image stack. Proceed ' ... - 'using only one stack for perfusion analysis?']) - %restnos = stressnos; - stressonly = true; - else - return - end - elseif isempty(stressnos) && ~hasalignedrest - if yesno(['Found only Perfusion Rest image stack. Proceed ' ... - 'using only one stack for perfusion analysis?']) - %stressnos = restnos; - restonly = true; - else - return - end - else %none is empty - mywarning(['Found more than one rest or stress image stack. ' ... - 'Taking first (arbitrary decision).']); - end -end - -DATA.GUI.PerfusionScoring = mygui('+perfusion/perfusionscoring.fig'); -gui=DATA.GUI.PerfusionScoring; -gui.currenttag='stress'; -gui.stressonly = stressonly; -gui.restonly = restonly; -gui.hidelv=0; - - -if stressonly - set(gui.handles.stresstimebaraxes,'visible','on') -elseif restonly - set(gui.handles.resttimebaraxes,'visible','on') -else - set(gui.handles.stresstimebaraxes,'visible','on') - set(gui.handles.resttimebaraxes,'visible','on') -end - -if ~isempty(stressnos) - gui.stressno = stressnos(1); -else - gui.stressno = []; -end -if ~isempty(restnos) - gui.restno = restnos(1); -else - gui.restno = []; -end - -if ~isempty(scarnos) - gui.scarno = scarnos(1); -else - gui.scarno = []; - set(gui.handles.scaraxes, 'Visible', 'off') -end - -%Determine which slices to use -inds=[gui.stressno, gui.restno]; -[~,nslicestack]=min([SET(inds).ZSize]); -nslicestack = inds(nslicestack); -gui.stressslices=[]; -gui.restslices=[]; -gui.scarslices=[]; - -if gui.stressonly - gui.stressslices=1:SET(gui.stressno).ZSize; - - gui.mrest = zeros(24,4); - if isfield(SET(gui.stressno).PerfusionScoring,'mstress') && ~isempty(SET(gui.stressno).PerfusionScoring.mstress) - gui.mstress = SET(gui.stressno).PerfusionScoring.mstress; - else - gui.mstress = zeros(24,4); - end - -elseif gui.restonly; - gui.restslices=1:SET(gui.restno).ZSize; - - gui.mstress = zeros(24,4); - - if isfield(SET(gui.restno).PerfusionScoring,'mrest') && ~isempty(SET(gui.restno).PerfusionScoring.mrest) - gui.mrest = SET(gui.restno).PerfusionScoring.mrest; - else - gui.mrest = zeros(24,4); - end - -else - gui.stressslices=1:SET(nslicestack).ZSize; - gui.restslices=1:SET(nslicestack).ZSize; - - [gui.stressslices,~,~,~,~,~] = segmentation('findmatchingslices', ... - nslicestack,gui.stressno,0,0,0,0,0,0); - [gui.restslices,~,~,~,~,~] = segmentation('findmatchingslices', ... - nslicestack,gui.restno,0,0,0,0,0,0); - - if isfield(SET(gui.stressno).PerfusionScoring,'mstress') && ~isempty(SET(gui.stressno).PerfusionScoring.mstress) - gui.mstress = SET(gui.stressno).PerfusionScoring.mstress; - else - gui.mstress = zeros(24,4); - end - - if isfield(SET(gui.restno).PerfusionScoring,'mrest') && ~isempty(SET(gui.restno).PerfusionScoring.mrest) - gui.mrest = SET(gui.restno).PerfusionScoring.mrest; - else - gui.mrest = zeros(24,4); - end - -end - -if ~isempty(gui.scarno) - [gui.scarslices,~,~,~,~,~] = segmentation('findmatchingslices', ... - nslicestack,gui.scarno,0,0,0,0,0,0); -end - -if ~isrow(gui.stressslices) - gui.stressslices=gui.stressslices'; -end -if ~isrow(gui.restslices) - gui.restslices=gui.restslices'; -end -if ~isrow(gui.scarslices) - gui.scarslices=gui.scarslices'; -end - -if ~isempty(gui.scarno) - if isfield(SET(gui.scarno).PerfusionScoring,'mscar') && ~isempty(SET(gui.scarno).PerfusionScoring.mscar) - gui.mscar=SET(gui.scarno).PerfusionScoring.mscar; - else - gui.mscar = zeros(24,4); - end -else - gui.mscar = zeros(24,4); -end - -gui.mdiff = gui.mstress-gui.mrest; - -fcn = @(hObject,eventdata)perfusion.perfusionscoring('timebaraxes_ButtonDownFcn',hObject,eventdata); -set(gui.fig,'WindowButtonDownFcn',fcn); - -segment('recursekeypressfcn',gui.fig,@(hObject,eventdata)perfusion.perfusionscoring('keypress_Callback',eventdata)) -load('newicons.mat','newicons') - -gui.Icons=newicons; -gui.iconholder = myiconplaceholder(gui.handles.iconaxes,0,1,gui.fig); -initiconholder; - -%indent autozoom -indent(gui.iconholder,'autozoom',0); - -% %estimate rotation; -% impos1 = SET(gui.stressno).ImagePosition; -% impos2 = SET(gui.restno).ImagePosition; -% imo1 = SET(gui.stressno).ImageOrientation(1:3); -% imo2 = SET(gui.restno).ImageOrientation(1:3); -% -% theta = acos(imo1/norm(imo1)*imo2'/norm(imo2))/pi*180; -% -% im1 = SET(gui.stressno).IM(:,:,1,1); -% im2 = SET(gui.restno).IM(:,:,1,1); -% im3 = SET(gui.scarno).IM(:,:,1,1); - -% fig = figure; -% subplot(121) -% imagesc(im1); -% subplot(122) -% imagesc(imrotate(im2,rad)) - gui.autozoom=1; - -set(gui.fig,'WindowButtonMotionFcn','perfusion.perfusionscoring(''motionfunc'')'); -gui.resttf=1; -gui.stresstf=1; -gui.scartf=1; -gui.restn=[]; -gui.stressn=[]; -gui.scarn=[]; -%gui.cinetf=1; - -if ~isempty(gui.restno) - gui.restn=SET(gui.restno).TSize; -end -if ~isempty(gui.stressno) - gui.stressn=SET(gui.stressno).TSize; -end -if ~isempty(gui.scarno) - gui.scarn=SET(gui.scarno).TSize; -end -% if ~isempty(gui.cineno) -% gui.cinen=SET(gui.cineno).TSize; -% end - -%gui.cineplay=0; -gui.restplay=0; -gui.stressplay=0; -gui.play=0; - -% for type={'stress','rest','scar'} -% generateimages(type{1}); -% end - - -%Initiate imageaxis and timebar -for imname = {'stress','rest'} - autozoom(imname{1}); - generateimages(imname{1}); - initimageaxis(imname{:}); - inittimebar(imname{1}) - settimeframe('currenttime',1,imname{1}) - %inittimebar(imname{:},analysed); -end - -autozoom('scar'); -generateimages('scar'); -initimageaxis('scar'); -generatebullseye('stress') -generatebullseye('rest') -%generatebullseye('scar') -generatebullseye('diff') - -% for type={'Stress','Rest'} -% title(gui.handles.(['bullseyeaxes',lower(type{1})]),['\fontsize{14}',type{1}]) -% end -% title(gui.handles.diffaxes,['\fontsize{14}','Diff']) - -save2set - - -%--------------------------- -function generateimages(type) -%--------------------------- - -global SET DATA -gui = DATA.GUI.PerfusionScoring; -no = gui.([type,'no']); -if isempty(no) - return; -end - - -xsz=SET(no).XSize; -ysz=SET(no).YSize; -T = gui.([type,'n']); -slices = gui.([type,'slices']); -%this was taken from a really nicely orientated cine SAX -% 0.7598 0.6030 -0.2431 -0.4615 0.2369 -0.8549 -imoref = [0.7598, 0.6030, -0.2431]; -imorefn= [-0.4579 0.7617 0.4583]; -imo = SET(no).ImageOrientation(1:3)/norm(SET(no).ImageOrientation(1:3)); - - -% figure; -% plot3([0 imo(1)],[0 imo(2)],[0 imo(3)],'r'); -imo=imo-(imorefn*imo')*imorefn; -% hold on; -% plot3([0 imo(1)],[0 imo(2)],[0 imo(3)],'c'); -% -% plot3([0 imorefn(1)],[0 imorefn(2)],[0 imorefn(3)],'g') - - -theta= acos(imoref/norm(imoref)*imo'/norm(imo))/pi*180; -xlim = gui.([type, 'xlim']); -ylim = gui.([type, 'ylim']); -% xscale=gui.([type,'xscale']); -% yscale=gui.([type,'yscale']); -scale =gui.([type,'scale']); -im=[]; -for tf=1:T - tmp=[]; - for i = slices - tmp= cat(2,tmp, imresize(imrotate(squeeze(SET(no).IM(xlim,ylim,tf,i)),theta,'bilinear','crop'),scale*[xsz ysz],'bilinear')); - end - im=cat(3,im,tmp); -end - -% for slice = slices -% im=imresize(imrotate(SET(no).IM(xlim,ylim,:,slice),theta),[]); -% end - gui.([type 'im'])=im; -% figure;subplot(121) -% imagesc(im(:,:,1)) -% subplot(122) -% imagesc(SET(1).IM(:,:,8,1)) - -%--------------------- -function resize_fcn -%--------------------- - -try - global DATA - persistent chk - - if ~isempty(chk) - return - else - chk=1; - end - - if isfield(DATA.GUI,'PerfusionScoring') - gui = DATA.GUI.PerfusionScoring; - try - render(gui.iconholder); - drawnow - catch - %it wasnt there - end - end - - chk=[]; -catch -%no data loaded -end - -%--------------------- -function motionfunc -%----------------------- -%motion function in the perfusionscoring gui. -global DATA - -gui = DATA.GUI.PerfusionScoring; -motion(gui.iconholder); - -%--------------------- -function initiconholder -%----------------------- -%initiates the iconholder in the perfusionscoring interface -global DATA -gui = DATA.GUI.PerfusionScoring; - -iconcell={}; -iconcell{1,end+1}=myicon('playstress',gui.iconholder,gui.Icons.playstress,'Play stress stack',@() perfusion.perfusionscoring('play','stress'),2,1); -iconcell{1,end+1}=myicon('playrest',gui.iconholder,gui.Icons.playrest,'Play rest stack',@() perfusion.perfusionscoring('play','rest'),2,1); -iconcell{1,end+1}=myicon('playall',gui.iconholder,gui.Icons.play,'Play all stacks',@() perfusion.perfusionscoring('playall'),2,1); -%iconcell{1,end+1}=myicon('hidesegmentation',gui.iconholder,gui.Icons.hidelv,'Hide icons',@() perfusion.perfusionscoring('hidecontour'),2); -iconcell{1,end+1}=myicon('autozoom',gui.iconholder,gui.Icons.autozoom,'Auto zoom',@() perfusion.perfusionscoring('autozoomtoggle'),2); -add(gui.iconholder,iconcell)%gui.iconholder.add(iconcell); -%render(gui.iconholder) - -%---------------------------- -function autozoomtoggle -%---------------------- -- - global DATA SET - gui = DATA.GUI.PerfusionScoring; - - if gui.autozoom - gui.autozoom=0; - if ~isempty(gui.scarno) - gui.scarxlim=1:SET(gui.scarno).XSize; - gui.scarylim=1:SET(gui.scarno).YSize; - else - gui.scarxlim=[]; - gui.scarylim=[]; - end - - if ~isempty(gui.stressno) - gui.stressxlim=1:SET(gui.stressno).XSize; - gui.stressylim=1:SET(gui.stressno).YSize; - else - gui.stressxlim=[]; - gui.stressylim=[]; - end - - if ~isempty(gui.restno) - gui.restxlim=1:SET(gui.restno).XSize; - gui.restylim=1:SET(gui.restno).YSize; - else - gui.restxlim=[]; - gui.restylim=[]; - end - - for type = {'scar', 'rest', 'stress'} - generateimages(type{1}); - initimageaxis(type{1}) - end - - else - - gui.autozoom=1; - for type = {'scar', 'rest', 'stress'} - autozoom(type{1}); - generateimages(type{1}); - initimageaxis(type{1}); - end - end - colormap([153/255 204/255 1;1 0.95 0;1 0 0]) -%---------------------------- - function autozoom(type) -%----------------------- -%function which finds larges epicardial contour and crops image a fixed -%distance from it. -global DATA %SET - -gui = DATA.GUI.PerfusionScoring; - -no=gui.([type,'no']); - -if isempty(no) - return -end -cinesaxno = findfunctions('findcineshortaxisno'); -if ~isempty(cinesaxno) - %[~,xlim,ylim] = segment('getbox',cinesaxno,no); - [xlim,ylim] = segment('getbox',cinesaxno,no,1); -else - [xlim,ylim] = segment('getbox',no,no,1); -end -gui.([type,'xlim']) = xlim(1):xlim(end); -gui.([type,'ylim']) = ylim(1):ylim(end); -if ylim(end)-ylim(1)>=xlim(end)-xlim(1) - gui.([type,'scale']) = 180/(ylim(end)-ylim(1)+1); - else - gui.([type,'scale']) = 180/(xlim(end)-xlim(1)+1); - end - -% -% slices=gui.([type,'slices']); -% xsz=SET(no).XSize; -% ysz=SET(no).YSize; -% -% if ~isempty(SET(no).EpiX) && ~all(all(all(isnan(SET(no).EpiX(:,:,slices))))) -% -% epix = SET(no).EpiX(:,:,slices); -% epiy = SET(no).EpiY(:,:,slices); -% -% xmin = floor(min(epix(:))); -% ymin = floor(min(epiy(:))); -% xmax = ceil(max(epix(:))); -% ymax = ceil(max(epiy(:))); -% -% dia = round(norm([xmax,ymax]-[xmin,ymin])/2*0.75); -% xmin=xmin-dia; -% ymin=ymin-dia; -% xmax=xmax+dia; -% ymax=ymax+dia; -% -% %make square cut? -% %min(abs([xmin-xmax,ymin-ymax])) -% -% if xmin<1 -% xmin=1; -% end -% -% if ymin<1 -% ymin=1; -% end -% -% if xmax>xsz -% xmax=xsz; -% end -% -% if ymax>ysz -% ymax=ysz; -% end -% -% %this catches segmentation blow ups -% if ymax-ymin<20 -% ymin=1; -% ymax=ysz; -% end -% -% if xmax-xmin<20 -% xmin=1; -% xmax=xsz; -% end -% -% if ymax-ymin>=xmax-xmin -% gui.([type,'yscale']) = 180/(ymax-ymin+1); -% gui.([type,'xscale']) = gui.([type,'yscale']);%*(ymax-ymin+1)/(xmax-xmin+1);%120/(ymax-ymin+1); -% else -% gui.([type,'xscale']) = 180/(xmax-xmin+1); -% gui.([type,'yscale']) = gui.([type,'xscale']);%*(xmax-xmin+1)/(ymax-ymin+1); -% end -% gui.([type,'xlim']) = xmin:xmax; -% gui.([type,'ylim']) = ymin:ymax; -% -% else -% im= SET(no).IM(:,:,:,slices); -% [xlim,ylim] = autocrop(im); -% -% if isempty(xlim) -% xmin=1; -% xmax=xsz; -% else -% xmin=xlim(1); -% xmax=xlim(end); -% end -% -% if isempty(ylim) -% ymin=1; -% ymax=ysz; -% else -% ymin=ylim(1); -% ymax=ylim(end); -% end -% -% if ymax-ymin>=xmax-xmin -% gui.([type,'yscale']) = 180/(ymax-ymin+1); -% gui.([type,'xscale']) = gui.([type,'yscale']);%*(ymax-ymin+1)/(xmax-xmin+1);%120/(ymax-ymin+1); -% else -% gui.([type,'xscale']) = 180/(xmax-xmin+1); -% gui.([type,'yscale']) = gui.([type,'xscale']);%*(xmax-xmin+1)/(ymax-ymin+1); -% end -% -% gui.([type,'xlim']) = xmin:xmax; -% gui.([type,'ylim']) = ymin:ymax; -% end - -%--------------------------------------- -function togglemode(type) -%--------------------------------------- -global DATA -gui = DATA.GUI.PerfusionScoring; -gui.currenttag=type; - - - -%---------------------------- -function initimageaxis(field) -%---------------------------- -%Initiate image axis with images from current stack -global DATA SET -gui = DATA.GUI.PerfusionScoring; -handles = gui.handles; -h = handles.([field 'axes']); -no = gui.([field 'no']); -tf = gui.([field 'tf']); -slices = gui.([field,'slices']); - -cla(h) - -if isempty(no) - return -end - -for hloop = h' - hold(hloop,'on'); - %axis(hloop,[0 1 0 1]); - axis(hloop,'ij');%'equal' - if ~isempty(SET(no).Colormap) - colormap(hloop,SET(no).Colormap) - else - colormap(hloop,'gray') - end -end - -% xlim = gui.([field, 'xlim']); -% ylim = gui.([field, 'ylim']); -% xsz=xlim(end)-xlim(1); -% ysz=ylim(end)-ylim(1); -% -% xscale=gui.([field,'xscale']); -% yscale=gui.([field,'yscale']); -% %gui.([field,'im'])=[]; -% im=[]; -%for i = slices - %im = [im, imresize(squeeze(SET(no).IM(xlim,ylim,tf,i)),[xscale*xsz yscale*ysz],'bilinear')]; -%end -im = gui.([field, 'im']); -im=im(:,:,tf); -%plot images -cmap = gray(256); -c = SET(no).IntensityMapping.Contrast; -b = SET(no).IntensityMapping.Brightness; -rim = segment('remap',im,cmap(:,1),c,b); -gim = segment('remap',im,cmap(:,2),c,b); -bim = segment('remap',im,cmap(:,3),c,b); -im = cat(3,rim, gim, bim); - gui.([field,'imhandle']) = image(im,'parent',h); - set(gui.([field,'imhandle']),'buttondownfcn',sprintf('perfusion.perfusionscoring(''togglemode'',''%s'')',field)) - axis(h,'image') -% xlim(h,gui.([field,'xlim'])) -% ylim(h,gui.([field,'ylim'])) - -if ~strcmp('scar',field) -pos = plotboxpos(gui.handles.([field,'axes'])); -set(gui.handles.([field,'timebaraxes']),'position',[pos(1)+pos(3)/5,pos(2)-0.027,3*pos(3)/5,0.02]) -end - -%initcontours - %zsz = SET(gui.([field,'no'])).ZSize; -% xsz = SET(no).XSize; -% ysz = SET(gui.([field,'no'])).YSize; -% xres = SET(gui.([field,'no'])).ResolutionX; -% yres = SET(gui.([field,'no'])).ResolutionY; -% set(gui.handles.([field,'axes']),'plotboxaspectratio',[zsz*ysz*yres xsz*xres 1]); -% xlim = gui.([field,'xlim']); -% ylim = gui.([field,'ylim']); -% xmin = xlim(1); -% ymin = ylim(1); -% ymax = ylim(end); -% -% xscale = gui.([field,'xscale']); -% yscale = gui.([field,'yscale']); -% if ~isempty(SET(no).EndoX) -% x=[]; -% y=[]; -% for i = 1:length(slices) -% x = [x;nan;xscale*(SET(no).EndoX(:,tf,slices(i))-xmin)+1]; -% y = [y;nan;yscale*(SET(no).EndoY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; -% end -% gui.([field,'endoseghandle']) = plot(h,y,x,'r'); -% else -% gui.([field,'endoseghandle']) = plot(h,nan,nan,'r'); -% end -% -% if ~isempty(SET(no).EpiX) -% x=[]; -% y=[]; -% for i = 1:length(slices) -% x = [x;nan;xscale*(SET(no).EpiX(:,tf,slices(i))-xmin)+1]; -% y = [y;nan;yscale*(SET(no).EpiY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; -% end -% gui.([field,'episeghandle']) = plot(h,y,x,'g'); -% else -% gui.([field,'episeghandle']) = plot(h,nan,nan,'g'); -% end -% -% if ~isempty(SET(no).RVEndoX) -% x=[]; -% y=[]; -% for i = 1:length(slices) -% x = [x;nan;xscale*(SET(no).RVEndoX(:,tf,slices(i))-xmin)+1]; -% y = [y;nan;yscale*(SET(no).RVEndoY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; -% end -% gui.([field,'rvendoseghandle']) = plot(h,y,x,'m'); -% else -% gui.([field,'rvendoseghandle']) = plot(h,nan,nan,'m'); -% end -% -% if ~isempty(SET(no).RVEpiX) -% x=[]; -% y=[]; -% for i = 1:length(slices) -% x = [x;nan;xscale*(SET(no).RVEpiX(:,tf,slices(i))-xmin)+1]; -% y = [y;nan;yscale*(SET(no).RVEpiY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; -% end -% gui.([field,'rvepiseghandle']) = plot(h,y,x,'c'); -% else -% gui.([field,'rvepiseghandle']) = plot(h,nan,nan,'c'); -% end - - - %drawimages(field); -%----------------------------------------- -function autodetectstartstop -%------------------------------------ -global DATA SET - -gui = DATA.GUI.PerfusionScoring; - -activation = zeros(1,gui.stressn); - -for t=1:gui.stressn - activation(t) = sum(sum(sum(squeeze(SET(gui.stressno).IM(:,:,t,gui.stressslices))))); -end - -%----------------------------------- -function inittimebar(field) -%----------------------------------- -%Initiate timebar axis for image specified by input parameter 'field'. -global DATA SET -gui = DATA.GUI.PerfusionScoring; -h = gui.handles.([field 'timebaraxes']); -no = gui.([field 'no']); - -if isempty(no) - return -end - -if gui.stressonly && strcmp(field,'rest') -return -end - -if gui.restonly && strcmp(field,'stress') -return -end - -delete(get(h,'Children')); - -tvec = SET(no).TimeVector; - -hold(h,'on'); -fcn = @(hObject,eventdata)perfusion.perfusionscoring('timebar_ButtonDownFcn',hObject,eventdata,field); - -%Draw timebar (red) and set its buttondown fcn -timebar = plot(h,tvec(SET(no).CurrentTimeFrame)*[1 1],[0 1],'r','Tag','currenttime','linewidth',2); -set(timebar,'ButtonDownFcn',fcn); -set(h,'fontsize',14) -%Draw start and end bars (blue) and set buttondown fcns - -% endtime = tvec(SET(no).EndAnalysis); -% plot(h,endtime*[1 1],[0 1],'b','Tag','endtime','ButtonDownFcn',fcn,'linewidth',2); -% text(endtime,0.9,'End','Parent',h,'Tag','endtext','ButtonDownFcn',fcn); -% -% starttime = tvec(SET(no).StartAnalysis); -% plot(h,starttime*[1 1],[0 1],'b','Tag','starttime','ButtonDownFcn',fcn,'linewidth',2); -% text(starttime,0.9,'Start','Parent',h,'Tag','starttext',... -% 'ButtonDownFcn',fcn,'HorizontalAlignment','right'); - - -updatetimebar(field); - -%---------------------------------- -function settimeframe(tag,tf,field) -%---------------------------------- -%Sets current/start/end timeframe for image stack specified by input -%parameter 'field' -global DATA SET -gui = DATA.GUI.PerfusionScoring; -no = gui.([field 'no']); - -if isempty(no) - return -end - -switch tag - case 'currenttime' - SET(no).CurrentTimeFrame = max(min(tf,SET(no).TSize),1); - gui.([field,'tf']) = SET(no).CurrentTimeFrame; - case {'starttime','starttext'} - SET(no).StartAnalysis = max(min(tf,SET(no).EndAnalysis),1); - case {'endtime','endtext'} - SET(no).EndAnalysis = max(min(tf,SET(no).TSize),SET(no).StartAnalysis); -end -drawimages(field); -updatetimebar(field); - - -%---------------------------------------------------- - function keypress_Callback(evnt) - %--------------------------------------------------- - global DATA - gui = DATA.GUI.PerfusionScoring; - currenttag = get(get(gui.fig,'currentaxes'),'tag'); - - if isempty(currenttag) || ~strcmp(currenttag,'iconaxes') - currenttag=gui.currenttag; - end - - key=getkey(evnt); - - switch key - case 'rightarrow' - - if regexp(currenttag,'stress') - - tf = gui.stresstf+1; - if tf>gui.stressn - tf=1; - end - settimeframe('currenttime',tf,'stress') - end - - if regexp(currenttag,'rest') - tf=gui.resttf+1; - if tf>gui.restn - tf=1; - end - settimeframe('currenttime',tf,'rest') - end - - case 'leftarrow' - - if regexp(currenttag,'stress') - tf = gui.stresstf-1; - if tf<1 - tf=gui.stressn; - end - settimeframe('currenttime',tf,'stress') - end - - if regexp(currenttag,'rest') - tf=gui.resttf-1; - if tf<1 - tf=gui.restn; - end - settimeframe('currenttime',tf,'rest') - end - - case 'shift-rightarrow' - if gui.restonly - ref_tf=(gui.resttf+1)/gui.restn; - - if ref_tf>1; - ref_tf=1/gui.restn; - end - - else - ref_tf=(gui.stresstf+1)/gui.stressn; - - if ref_tf>1; - ref_tf=1/gui.stressn; - end - end - for type = {'stress','rest'}%,'cine'} - % pick tf closest to current stress or rest if restonly frame - T=gui.([type{1}, 'n']); - [~,tf] = min(abs(ref_tf-(1:T)/T)); - settimeframe('currenttime',tf,type{1}) - end - case 'shift-leftarrow' - if gui.restonly - ref_tf=(gui.resttf-1)/gui.restn; - - if ref_tf<1/gui.restn; - ref_tf=1; - end - - else - ref_tf=(gui.stresstf-1)/gui.stressn; - - if ref_tf<1/gui.stressn; - ref_tf=1; - end - end - for type = {'stress','rest'}%,'cine'} - % pick tf closest to current stress or rest if restonly frame - T=gui.([type{1}, 'n']); - [~,tf] = min(abs(ref_tf-(1:T)/T)); - settimeframe('currenttime',tf,type{1}) - end - case 'p' - if ~gui.play - indent(gui.iconholder,'playall',1) - else - undent(gui.iconholder,'playall',1) - end - end - -%---------------------------------------------------- -function timebaraxes_ButtonDownFcn(hObject, ~) -%---------------------------------------------------- -%Buttondown function for timebar axes of image specified by input -%parameter 'field'. Changes current timeframe to the one closest to -%position of clicked point -global DATA SET -gui = DATA.GUI.PerfusionScoring; -handleAddress=hittest(hObject); -try -switch get(handleAddress,'tag') - case 'stresstimebaraxes' - field='stress'; - case 'resttimebaraxes' - field='rest'; - otherwise - return -end -catch -return; -end -gui.currenttag=field; -no = gui.([field 'no']); -[x,y] = mygetcurrentpoint(handleAddress); -[~,tvix] = min(abs(SET(no).TimeVector-x)); -settimeframe('currenttime',tvix,field); -kids=get(handleAddress,'children'); -obj=kids(strcmp('currenttime',get(kids,'tag'))); - -if isempty(obj) - return -end - -motionfcn = @(hObject,eventdata)perfusion.perfusionscoring('timebaraxes_MotionFcn',hObject,eventdata,obj,no,field,1); -set(gui.fig,'WindowButtonMotionFcn',motionfcn); -buttonupfcn = @(hObject,eventdata)perfusion.perfusionscoring('timebaraxes_ButtonUpFcn',hObject,eventdata); -set(gui.fig,'WindowButtonUpFcn', buttonupfcn); - -%------------------------------------------------ -function timebar_ButtonDownFcn(hObject, ~, field) -%------------------------------------------------ -%Buttondown function for graphical timebar object of image specified -%by input parameter 'field'. Activates dragging of timebars. -global DATA -gui = DATA.GUI.PerfusionScoring; -no = gui.([field 'no']); -obj = hObject; -motionfcn = @(hObject,eventdata)perfusion.perfusionscoring('timebaraxes_MotionFcn',hObject,eventdata,obj,no,field); -set(gui.fig,'WindowButtonMotionFcn',motionfcn); -buttonupfcn = @(hObject,eventdata)perfusion.perfusionscoring('timebaraxes_ButtonUpFcn',hObject,eventdata); -set(gui.fig,'WindowButtonUpFcn', buttonupfcn); - - -%----------------------------------------------------------- -function timebaraxes_MotionFcn(hObject, ~, tbobj, no, field,axesclick) -%----------------------------------------------------------- -%Mouse motion function for timebar axes of image specified by input -%parameter 'field'. Used for dragging timebars to change current -%timeframe or start/end points of timeframes in which to align images. -global SET - -if nargin<6 - axesclick=0; -end - -x = mygetcurrentpoint(get(tbobj,'Parent')); -[~,tvix] = min(abs(SET(no).TimeVector-x)); -settimeframe(get(tbobj,'Tag'),tvix,field); - -%------------------------------------------- -function timebaraxes_ButtonUpFcn(hObject, ~) -%------------------------------------------- -%Buttonup function for timebar axes of image specified by input -%parameter 'field'. Deactivates dragging of timebar. -set(hObject,'WindowButtonMotionFcn',[],'WindowButtonUpFcn',[]); - - - -%--------------------------- -function updatetimebar(field) -%--------------------------- -%Update timebar axis specified by handle 'h' from input arguments -global DATA SET -gui = DATA.GUI.PerfusionScoring; -h = gui.handles.([field 'timebaraxes']); -no = gui.([field,'no']); - -fcn = get(h,'ButtonDownFcn'); -tvec = SET(no).TimeVector; -tmin = tvec(1); -tmax = tvec(end); - -starttime = tvec(SET(no).StartAnalysis); -endtime = tvec(SET(no).EndAnalysis); -currenttime = tvec(SET(no).CurrentTimeFrame); %#ok - -%Update timebars -for kid = get(h,'Children')' - tag = get(kid,'Tag'); - switch tag - case {'starttime','endtime','currenttime'} - eval(sprintf('set(kid,''XData'',%s*[1 1])',tag)); - case 'starttext' - set(kid,'Position',[starttime 0.9 0]); - case 'endtext' - set(kid,'Position',[endtime 0.9 0]); - end -end - -%Set axes options -marg = (tmax-tmin)/100; -axis(h,[tmin-marg tmax+marg 0 1]); -tstep = 5*ceil((tmax-tmin)/40); -tickvec = [ceil(tmin/tstep)*tstep:tstep:floor(tmax/tstep)*tstep]; -set(h, 'Xtick', tickvec,'YTick',[],'XMinorTick','on'); -set(h,'ButtonDownFcn',fcn); - -%------------------------- -function drawimages(field) -%------------------------- -%Do an update of all image axes -global DATA SET -gui = DATA.GUI.PerfusionScoring; -no = gui.([field 'no']); -tf=gui.([field,'tf']); - -if isempty(no) - return -end - -if strcmp(field,'stress') && gui.restonly || ... - strcmp(field,'rest') && gui.stressonly - return -end - -h = gui.handles.([field 'axes']); - -%gui.([field,'im'])=[]; - -xlim = gui.([field, 'xlim']); -ylim = gui.([field, 'ylim']); -% xsz=xlim(end)-xlim(1); -% ysz=ylim(end)-ylim(1); - -% xscale=gui.([field,'xscale']); -% yscale=gui.([field,'yscale']); - -% for i = gui.([field,'slices']) -% gui.([field,'im']) = [gui.([field,'im']), imresize(squeeze(SET(no).IM(gui.([field,'xlim']),gui.([field,'ylim']),tf,i)),[xscale*xsz yscale*ysz],'bilinear')];%squeeze(SET(gui.([field,'no'])).IM(xlim,ylim,tf,i))]; -% end -im=gui.([field,'im']); -im=im(:,:,tf); - -%plot images -cmap = gray(256); -c = SET(gui.([field,'no'])).IntensityMapping.Contrast; -b = SET(gui.([field,'no'])).IntensityMapping.Brightness; -rim = segment('remap',im,cmap(:,1),c,b); -gim = segment('remap',im,cmap(:,2),c,b); -bim = segment('remap',im,cmap(:,3),c,b); -im = cat(3,rim, gim, bim); - set(gui.([field,'imhandle']),'Cdata', im) -% xlim(h,gui.([field,'xlim'])) -% ylim(h,gui.([field,'ylim'])) - %hidelv button indented - - %drawcontours(field) -% gui.endoseghandle = plot(SET(gui.([field,'no'])).EndoX,SET(gui.([field,'no'])).EndoY); -% gui.episeghandle = plot(SET(gui.([field,'no'])).EpiX,SET(gui.([field,'no'])).EpiY); -% gui.rvendoseghandle = plot(SET(gui.([field,'no'])).RVEndoX,SET(gui.([field,'no'])).RVEndoY); -% gui.rvepiseghandle = plot(SET(gui.([field,'no'])).RVEpiX,SET(gui.([field,'no'])).RVEpiY); -% end - %-------------------------------------- - function drawcontours(field) - %----------------------------------- - global DATA SET - - gui = DATA.GUI.PerfusionScoring; - no = gui.([field 'no']); - tf = gui.([field 'tf']); - slices = gui.([field, 'slices']); - xlim = gui.([field,'xlim']); - ylim = gui.([field,'ylim']); - xmin = xlim(1); - ymin = ylim(1); - ymax = ylim(end); - - scale = gui.([field,'scale']); - - if ~isempty(SET(no).EndoX) && ~gui.hidelv - x=[]; - y=[]; - for i = 1:length(slices) - x = [x;nan;scale*(SET(no).EndoX(:,tf,slices(i))-xmin)+1]; - y = [y;nan;scale*(SET(no).EndoY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; - end - set(gui.([field,'endoseghandle']),'XData',y,'YData',x)%plot(h,x,y); - else - set(gui.([field,'endoseghandle']), 'XData',nan,'YData',nan) - end - - if ~isempty(SET(no).EpiX) && ~gui.hidelv - x=[]; - y=[]; - for i = 1:length(slices) - x = [x;nan;scale*(SET(no).EpiX(:,tf,slices(i))-xmin)+1]; - y = [y;nan;scale*(SET(no).EpiY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; - end - set(gui.([field,'episeghandle']),'XData',y,'YData',x)%plot(h,x,y); - else - set(gui.([field,'episeghandle']), 'XData',nan,'YData',nan) - end - - if ~isempty(SET(no).RVEndoX) && ~gui.hidelv - x=[]; - y=[]; - for i = 1:length(slices) - x = [x;nan;scale*(SET(no).RVEndoX(:,tf,slices(i))-xmin)+1]; - y = [y;nan;scale*(SET(no).RVEndoY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; - end - set(gui.([field,'rvendoseghandle']),'XData',y,'YData',x)%plot(h,x,y); - else - set(gui.([field,'rvendoseghandle']), 'XData',nan,'YData',nan) - end - - if ~isempty(SET(no).RVEpiX) && ~gui.hidelv - x=[]; - y=[]; - for i = 1:length(slices) - x = [x;nan;scale*(SET(no).RVEpiX(:,tf,slices(i))-xmin)+1]; - y = [y;nan;scale*(SET(no).RVEpiY(:,tf,slices(i))+(ymax-ymin)*(i-1)-ymin)+1+(i-1)]; - end - set(gui.([field,'rvepiseghandle']),'XData',y,'YData',x)%plot(h,x,y); - else - set(gui.([field,'rvepiseghandle']), 'XData',nan,'YData',nan) - end - - %------------------- - function playcheck(type) - %----------------- - global DATA - gui = DATA.GUI.PerfusionScoring; - - if ~strcmp(type,'rest') && gui.restplay - %undent and stop rest play - gui.restplay=0; - undent(gui.iconholder.iconCell{2}) - render(gui.iconholder) - end - - if ~strcmp(type,'stress') && gui.stressplay - gui.stressplay=0; - undent(gui.iconholder.iconCell{1}) - render(gui.iconholder) - end - - if ~strcmp(type,'play') && gui.play - gui.play=0; - undent(gui.iconholder.iconCell{3}) - render(gui.iconholder) - end - - %--------------------------------- - function play(type) - %-------------------------------- - global DATA SET - - gui = DATA.GUI.PerfusionScoring; - no=gui.([type, 'no']); - - gui.([type,'play'])=~gui.([type,'play']); - - gui.currenttag=type; - playcheck(type) - - if isempty(no) - return - end - - try - while gui.([type,'play']) - gui.([type, 'tf']) = gui.([type, 'tf'])+1; - - if gui.([type, 'tf'])>gui.([type, 'n']) - gui.([type, 'tf'])=1; - end - - SET(no).CurrentTimeFrame=gui.([type, 'tf']); - - drawimages(type); - updatetimebar(type); - drawnow - %pause(0.001) - end - catch - %gui has been closed. - - mydisp('closed while playing') - return - end - -%--------------------------------- -function playall -%-------------------------------- -global DATA SET - -gui = DATA.GUI.PerfusionScoring; - -% if gui.stressonly -% play('stress') -% return -% end -% -% if gui.restonly -% play('rest') -% return -% end - -gui.play=~gui.play; - -playcheck('play') - -try -while gui.play - if gui.restonly - ref_tf=(gui.resttf+1)/gui.restn; - - if ref_tf>1; - ref_tf=1/gui.restn; - end - - else - ref_tf=(gui.stresstf+1)/gui.stressn; - - if ref_tf>1; - ref_tf=1/gui.stressn; - end - end - - if gui.stressonly - types = {'stress'}; - elseif gui.restonly - types={'rest'}; - else - types={'stress','rest'}; - end - - for type = types%,'cine'} - % pick tf closest to current stress or rest if restonly frame - T=gui.([type{1}, 'n']); - [~,gui.([type{1}, 'tf'])] = min(abs(ref_tf-(1:T)/T));%SET(gui.([type{1}, 'no'])).TSize)); - SET(gui.([type{1}, 'no'])).CurrentTimeFrame=gui.([type{1}, 'tf']); - drawimages(type{1}); - updatetimebar(type{1}); - end - drawnow - %pause(0.001) -end -catch - %closed while playing - mydisp('closed while playing') -end - -%-------------------- -function score(type) -%-------------- -%Updates perfusion scoring bullseye according to click -global DATA - -gui=DATA.GUI.PerfusionScoring; - -switch type - case 'stress' - gui.currenttag=type; - bullseyehandle=gui.handles.bullseyeaxesstress; - case 'rest' - gui.currenttag=type; - bullseyehandle=gui.handles.bullseyeaxesrest; - case 'scar' - return - %bullseyehandle=gui.handles.bullseyeaxesscar; -end -%first identify which region was clicked then update the correct m values -[x,y] = mygetcurrentpoint(bullseyehandle); - -xc=x-gui.center; -yc=y-gui.center; - -[theta,rho] = cart2pol(xc,yc); - -%determine slice - -%apex case completely handled here -if rho < 50 - %apex adjust m(1:4) then return - region=1; - sector='apex'; -end - -if rho >50 && rho <100 - region=2; -end - -if rho >100 && rho <150 -region=3; -end - -if rho >150 && rho <200 - region=4; -end - -if rho>200 - return -end - -%apical -if region == 2 - if abs(theta)pi/4 && theta <3*pi/4 - %inferior - sector = 'inferior'; - end - - if abs(theta) > 3*pi/4% || (theta >-pi/4 && theta < 0) - %septal - sector = 'septal'; - end - - if theta <-pi/4 && theta >-3*pi/4 - %anterior - sector ='anterior'; - end -end - - -%basal mid -if region >2 - if theta0 - %inferolateral - sector = 'inferolateral'; - end - - if theta >pi/3 && theta <2*pi/3 - %inferior - sector = 'inferior'; - end - - if theta >2*pi/3 && theta -pi/3 - %anteroseptal - sector = 'anterolateral'; - end - - if theta < -pi/3 && theta >-2*pi/3 - %anterior - sector = 'anterior'; - end - - if theta < -2*pi/3 && theta >-pi - %anterolateral - sector = 'anteroseptal'; - end -end - -clicktype = get(get(bullseyehandle,'parent'),'selectiontype'); - -switch clicktype - case 'open' - setsectionscore(type,region,sector,2) - case 'normal' %ordinary mouseclick add - setsectionscore(type,region,sector,1) - case {'alt','extend'} - setsectionscore(type,region,sector,0) -end - -generatebullseye(type) -gui.mdiff = gui.mstress - gui.mrest; -generatebullseye('diff') -save2set - -%------------------------------- -function setsectionscore(type,region,sector, incr) -%----------------------------- -global DATA - %Unpack vector to matrix - - gui=DATA.GUI.PerfusionScoring; - - switch sector - case 'anterior' - if region==2 - inds=[1, 2, 21, 22, 23, 24]; - else - inds=1:4; - end - - case 'anteroseptal' - inds=5:8; - - case 'inferoseptal' - inds=9:12; - - case 'inferior' - if region==2 - inds = 9:14; - else - inds = 13:16; - end - - case 'inferolateral' - inds=17:20; - - case 'anterolateral' - inds=21:24; - - case 'septal' - inds=3:8; - - case 'lateral' - inds=15:20; - - case 'apex' - inds=1:24; - end - - m = gui.(['m',type]); - if m(inds(1),region)==1 && incr==1 - incr=2; - elseif m(inds(1),region)==2 && incr==1 - incr=0; - end - - switch type - case 'rest' - gui.mrest(inds,region)=incr;%gui.mrest(inds(1),region)+incr; - case 'stress' - gui.mstress(inds,region)=incr;%gui.mstress(inds(1),region)+incr; - case 'scar' - gui.mscar(inds,region)=incr;%gui.mscar(inds(1),region)+incr; - end - - %--------------------- - function save2set - %--------------------- - global DATA SET - - gui=DATA.GUI.PerfusionScoring; - - outdata=cell(3,17); - for loop=1:17 - [stri,pos] = reportbullseye('aha17nameandpos',loop); %Get name and position of export - outdata{1,loop+1}=stri; - end - - counter=1; - for type={'stress','rest','diff'} - m=gui.(['m',type{1}]); - counter=counter+1; - outdata{counter,1}=type{1}; - outdata{counter,2} = mynanmean(m(1:4,4)); - outdata{counter,3} = mynanmean(m(5:8,4)); - outdata{counter,4} = mynanmean(m(9:12,4)); - outdata{counter,5} = mynanmean(m(13:16,4)); - outdata{counter,6} = mynanmean(m(17:20,4)); - outdata{counter,8} = mynanmean(m(21:24,4)); - %mid - outdata{counter,8} = mynanmean(m(1:4,3)); - outdata{counter,9} = mynanmean(m(5:8,3)); - outdata{counter,10} = mynanmean(m(9:12,3)); - outdata{counter,11} = mynanmean(m(13:16,3)); - outdata{counter,12} = mynanmean(m(17:20,3)); - outdata{counter,13} = mynanmean(m(21:24,3)); - %apical - outdata{counter,14} = mynanmean([m(1:2,2) ; m(21:24,2)]); - outdata{counter,15} = mynanmean(m(3:8,2)); - outdata{counter,16} = mynanmean(m(9:14,2)); - outdata{counter,17} = mynanmean(m(15:20,2)); - %apex - outdata{counter,18} = mynanmean(m(:,1)); - end - for type = {'stress','rest','scar'} - no=gui.([type{1},'no']); - if ~isempty(no) - SET(no).PerfusionScoring.export=outdata; - SET(no).PerfusionScoring.(['m',type{1}])=gui.(['m',type{1}]); - if any(strcmp(type{1},{'stress','rest'})) - SET(no).PerfusionScoring.mdiff=gui.mdiff; - end - SET(no).PerfusionScoring.stressno=gui.stressno; - SET(no).PerfusionScoring.restno=gui.restno; - SET(no).PerfusionScoring.scarno=gui.scarno; - end - end - - - %--------------------------- - function reset(type) - %------------------------ -global DATA -gui=DATA.GUI.PerfusionScoring; -gui.(['m',type])= zeros(24,4); -generatebullseye(type); - -gui.mdiff = gui.mstress - gui.mrest; -generatebullseye('diff'); -save2set - - %----------- -function generatebullseye(type,handle,no) -%----------- -global DATA - - -%Set up -ahanumslices = 3; -n = 200; -scale = n/(ahanumslices+1); -numsectors = 24; - -if nargin == 1; -gui=DATA.GUI.PerfusionScoring; -switch type - case 'rest' - m = gui.mrest; - bullseyehandle=gui.handles.bullseyeaxesrest; - case 'stress' - m=gui.mstress; - bullseyehandle=gui.handles.bullseyeaxesstress; - case 'diff' - m=gui.mdiff; - bullseyehandle=gui.handles.diffaxes; - case 'scar' - m=gui.mscar; - bullseyehandle=gui.handles.bullseyeaxesscar; -end -gui.center=n+1; -else - global SET - try - m=SET(no).PerfusionScoring.(['m',type]); - bullseyehandle=handle; - catch - mydisp('Perfusion Scoring not available') - return; - end -end - -set(bullseyehandle,'Color',[0 0 0],'Visible','on'); -[x,y] = ndgrid(... - linspace(-ahanumslices-1,ahanumslices+1,2*n+1),... - linspace(-ahanumslices-1,ahanumslices+1,2*n+1)); -rad = sqrt(x.*x+y.*y); - -%Createidx outer -ang = angle(complex(y,x))+pi; -ang = numsectors*ang/(2*pi); -ang = mod(-(ang-numsectors/3),numsectors); %orient it iaccording to sectors in AHA 17-segment model -idxouter = 1+min(floor(ang),(numsectors-1))+(numsectors)*min(floor(rad),ahanumslices); - -%Createidx inner -ang = mod(angle(complex(y,x))+pi+pi/4,2*pi); -ang = numsectors*ang/(2*pi); -ang = mod(-(ang-numsectors/3),numsectors); %orient it iaccording to sectors in AHA 17-segment model -idxinner = 1+min(floor(ang),(numsectors-1))+(numsectors)*min(floor(rad),ahanumslices); - -idx = idxouter; -idx(rad<2) = idxinner(rad<2); - -im = m(idx); -im(rad>(ahanumslices+1)) = NaN; -%im = rad; - -%View data -alpha = double(not(isnan(im))); -im(isnan(im)) = 0; -h = imagesc(im,'parent',bullseyehandle); - -set(h,'alphadata',alpha,'AlphaDataMapping','scaled'); -axis(bullseyehandle,'image','off'); -%cmap=[0.4259 0.2759 0.2759; 0.6045 0.3935 0.3935; 0.7412 0.4833 0.4833]; -%a=pink; -%cmap = [a(90,:);a(140,:);a(190,:)]; - -%pink one -%cmap=[0.7412 0.4833 0.4833; 0.8356 0.7230 0.6040;0.9107 0.9107 0.7043]; -cmap=[153/255 204/255 1;1 0.95 0;1 0 0]; -%cmap=[0.0598 0.6841 0.7247; 0.9696 0.7300 0.2706; 1 0 0]; -colormap(bullseyehandle,cmap); -caxis(bullseyehandle,[0 2]) - -if nargin == 1 - set(h,'ButtonDownFcn',sprintf('perfusion.perfusionscoring(''score'',''%s'')',type)); -end - -%Draw circles -om = linspace(0,2*pi,100); -xc = sin(om); -yc = cos(om); -hold(bullseyehandle,'on'); -for loop=1:(ahanumslices+1) - h = plot(bullseyehandle,n+1+scale*loop*xc,n+1+scale*loop*yc,'w-'); - set(h,'linewidth',2); -end; -hold(bullseyehandle,'off'); - -%Draw lines -hold(bullseyehandle,'on'); -b = sqrt(0.75); -a = 0.5; -c = 1/sqrt(2); -h = plot(bullseyehandle,scale*[0 2],scale*[4 4],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[6 8],scale*[4 4],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4-c 4-2*c],scale*[4-c 4-2*c],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4+c 4+2*c],scale*[4+c 4+2*c],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4-c 4-2*c],scale*[4+c 4+2*c],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4+c 4+2*c],scale*[4-c 4-2*c],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4-4*a 4-2*a],scale*[4-4*b 4-2*b],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4-4*a 4-2*a],scale*[4+4*b 4+2*b],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4+4*a 4+2*a],scale*[4+4*b 4+2*b],'w-'); set(h,'linewidth',2); -h = plot(bullseyehandle,scale*[4+4*a 4+2*a],scale*[4-4*b 4-2*b],'w-'); set(h,'linewidth',2); -hold(bullseyehandle,'off'); - -%print out the strain values in the bullseye -rloops = [1 4 6 6]; -for cloop=1:(ahanumslices+1) - for rloop = 1:rloops(cloop) - if cloop > 2 %basal and mid - r = max(1,mod(round(rloop*length(xc)/rloops(cloop)+2/6*length(xc)),length(xc))); - else - r = max(1,mod(round(rloop*length(xc)/rloops(cloop)+1/2*length(xc)),length(xc))); - end - if rloops(cloop) == 6 %basal and mid - mx = 1+(rloop-1)*4:4+(rloop-1)*4; - elseif rloops(cloop) == 4 %apical - if rloop == 4 - mx = [1:2 21:24]; - else - mx = 3+(rloop-1)*6:8+(rloop-1)*6; - end - else %apex - mx = 1:24; - end - value = (mynanmean(m(mx,cloop))); - if ~isnan(value) - text_handle=text(n+1+(scale/2*min(1,max(0,cloop-1))+scale*(cloop-1))*xc(r), ... - n+1+(scale/2*min(1,max(0,cloop-1))+scale*(cloop-1))*yc(r), ... - sprintf('%0.3g',value),'Parent',bullseyehandle,'HorizontalAlignment','center','fontweight','bold'); - - if nargin == 1 - set(text_handle,'ButtonDownFcn',sprintf('perfusion.perfusionscoring(''score'',''%s'')',type)); - end - - end - end -end; - -switch type - case 'stress' - title(bullseyehandle,dprintf('Stress'),'FontSize',14) - case 'rest' - title(bullseyehandle,dprintf('Rest/LGE'),'FontSize',14) - case 'diff' - title(bullseyehandle,dprintf('Diff'),'FontSize',14) -end -% colorbar('peer',gui.handles.bullseyeaxes); -% maxvalue = max(max(m(:)),abs(min(m(:)))); -% if isnan(maxvalue) || maxvalue==0 -% maxvalue = 1; -% end; -% set(gui.handles.bullseyeaxes,'clim',[-maxvalue maxvalue]); - - -%-------------------------------------------- -function close_Callback -%-------------------------------------------- -global DATA SET -try -gui=DATA.GUI.PerfusionScoring; -gui.play=0; -gui.stressplay=0; -gui.restplay=0; - -for type = {'stress' 'rest'} - SET(gui.([type{1},'no'])).PerfusionScoring.diffbullseye=frame2im(mygetframe(gui.handles.diffaxes)); -end - -for type = {'stress' 'rest' 'scar'} - SET(gui.([type{1},'no'])).PerfusionScoring.([type{1}, 'bullseye'])=frame2im(mygetframe(gui.handles.(['bullseyeaxes',type{1}]))); -end - -save2set - -close(gui) -catch -close(gcf) -end \ No newline at end of file diff --git a/source/+perfusion/perfusionscoring.p b/source/+perfusion/perfusionscoring.p new file mode 100644 index 0000000..767130d Binary files /dev/null and b/source/+perfusion/perfusionscoring.p differ diff --git a/source/+pwv/pulsewavevelocity.fig b/source/+pwv/pulsewavevelocity.fig index a0b10da..2d0c436 100644 Binary files a/source/+pwv/pulsewavevelocity.fig and b/source/+pwv/pulsewavevelocity.fig differ diff --git a/source/+pwv/pulsewavevelocity.p b/source/+pwv/pulsewavevelocity.p index 279a1bc..422ebe9 100644 Binary files a/source/+pwv/pulsewavevelocity.p and b/source/+pwv/pulsewavevelocity.p differ diff --git a/source/+reporter/figgenerator.m b/source/+reporter/figgenerator.m deleted file mode 100644 index 6fe7da2..0000000 --- a/source/+reporter/figgenerator.m +++ /dev/null @@ -1,363 +0,0 @@ -%FIGGENERATOR Class for generating figures containing text documents -%Position: [vänsterkant underkant bredd höjd] - -classdef figgenerator < handle - - properties - filename = ''; - pathname = ''; - title = ''; - allfigs = []; - figno = []; - lineht = 0; - pos = 0; - pagewidth = 0; - stf = struct; - end - - methods - - %--------------------------------------------------- - function fg = figgenerator(title, pathname, filename, pagewidth, lineht) - %--------------------------------------------------- - %Constructor - - if nargin < 5 - lineht = 14; - if nargin < 4 - pagewidth = 800; - if nargin < 3 - filename = [title '_%04.0f.jpg']; - if nargin < 2 - pathname = pwd; - end - end - end - end - fg.title = title; - fg.filename = filename; - fg.pathname = pathname; - fg.pagewidth = pagewidth; - fg.lineht = lineht; - fg.stf.fontname = 'courier new'; - end - - %--------------------------- - function start(fg, figtitle) - %--------------------------- - %START Method to open a new figure - - fg.figno = figure; - fg.allfigs = [fg.allfigs fg.figno]; - axis ij - %axis off - hold on - figpos = get(fg.figno,'position'); - figpos(3) = fg.pagewidth; - set(fg.figno,'position',figpos); - fg.pos = fg.lineht/2; - if nargin == 2 - title(figtitle); - end - end - - %---------------- - function zoom(fg) - %---------------- - %ZOOM Zoom to current page size - pageht = fg.pos+fg.lineht; - axis off - axis([0 fg.pagewidth 0 pageht]); - figpos = get(fg.figno, 'position'); - figpos(4) = pageht + 2*fg.lineht; - set(fg.figno, 'position', figpos); - end - - %----------------- - function hline(fg) - %----------------- - %HLINE Method to write a horizontal line - - return %Might not get this to work properly - figure(fg.figno) - fg.newline; - plot([0 fg.pagewidth],[fg.pos fg.pos],'k'); - fg.newline; - - end - - %--------------------------------------------------------- - function call = table(fg, content, boldcells, width, lpos) - %--------------------------------------------------------- - %TABLE Method to insert a table with content specified by a cell - - if nargin < 5 - lpos = 0; - if nargin < 4 - width = round(0.625*fg.pagewidth); - if nargin < 3 - boldcells = zeros(size(content)); - if nargin < 2 - myfailed('Too few input arguments.'); - end - end - end - end - - if nargout > 0 - call = @(lpos)table(fg,content,boldcells,width,lpos); - return - end - - startpos = fg.pos; - - for j = 1:size(content, 2) - maxwidth = max(cellfun(@length,content(:,j))); - lpos = [lpos lpos(end)+(maxwidth+3)*fg.lineht*10/14]; - end - - tpos = startpos; - for i = 1:size(content, 1) - for j = 1:size(content, 2) - if ~isempty(content{i,j}) - st = fg.stf; - if boldcells(i, j) == 2 - st.color = [1 0 0]; - elseif boldcells(i, j) - st.fontweight = 'bold'; - end - if ~isempty(regexp(content{i,j},'(²)', 'once')) - constri = regexprep(content{i,j},'(²)','^2'); - tpos = tpos + fg.lineht/4; - text(lpos(j), tpos, constri, st); - else - text(lpos(j), tpos, content{i,j}, st); - end - end - end - tpos = tpos + fg.lineht; - fg.newline; - end - - end - - %------------------------------------------- - function call = headline(fg, headtext, lpos) - %------------------------------------------- - %HEADLINE Method to write a headline in bold - if nargin < 3 - lpos = 0; - end - - if nargout > 0 - call = @(lpos)headline(fg, headtext, lpos); - return - end - - fg.newline; - text(lpos, fg.pos, headtext, 'fontsize', 16, 'fontweight', 'bold'); - fg.newline; - fg.newline; - end - - %----------------------------------------------------------- - function call = text(fg, paragraph, alignment, lpos, weight) - %----------------------------------------------------------- - %TEXT Method to write a paragraph of text - - if nargin < 5 - weight = 'normal'; - if nargin < 4 - lpos = 0; - if nargin < 3 - alignment = 'left'; - end - end - end - - if nargout > 0 - call = @(lpos)text(fg, paragraph, alignment, lpos); - return - end - - st = fg.stf; - if nargin == 3 - st.horizontalalignment = alignment; - if strcmp(alignment,'right') - lpos = fg.pagewidth; - end - end - h = text(lpos, fg.pos, paragraph, st); - set(h,'FontWeight',weight); - fg.newline; - end - - - %------------ - function gsstri = ftext(fg) - %------------ - %FTEXT Method to write a paragraph of text with formatted headlines. - global SET - %stri = []; - gsstri = []; %Gensvar string (unformatted) - cr = []; - prow = 1; %Variable to keep track of row number in current paragraph - %Convert from Matlab string matrix to viewable text - for row = 1:size(SET(1).Report.Comments,1) - crprev = cr; - cr = deblank(SET(1).Report.Comments(row,:)); - gsstri = [gsstri cr sprintf('\n')]; %#ok - if isempty(cr) %Insert new paragraph if a line is blank - %stri = [stri sprintf('\n

\n

\n')]; %#ok - if ~isempty(crprev) - fg.text(crprev); - end - fg.newline; - prow = 1; - else - if prow == 2 %Create headline according to rules of formatting (see manual) - if strcmp(upper(crprev),crprev) - %stri = regexprep(stri,crprev,sprintf('

%s

',crprev)); %superheadline - fg.text(crprev,'left',0,'bold'); - %fg.text(cr); - prow = 1; - else - %stri = regexprep(stri,crprev,sprintf('

%s

',crprev)); %subheadline - fg.text(crprev,'left',0,'bold'); - %fg.text(cr); - end - elseif prow > 2 - fg.text(crprev); - fg.newline; - %stri = [stri sprintf('
\n')]; %#ok - end - %stri = [stri sprintf('%s\n',cr)]; %#ok - prow = prow + 1; - end - end - fg.text(cr); - - end - - %-------------------------------------------------- - function call = image(fg, imgname, imgsource, lpos) - %-------------------------------------------------- - %IMAGE Method to add an image. imgsource can be a - %location or an image matrix. - - if nargout > 0 - call = @(lpos)image(fg, imgname, imgsource, lpos); - return - end - - if nargin < 4 - lpos = 0; - end - - if ischar(imgsource) - try - imgsource = imread(imgsource); - catch me - mydispexception(me); - error('Could not read image file'); - end - end - sz = size(imgsource); - newpos = fg.pos + sz(1); - fg.newline; - imagesc([lpos lpos+sz(2)], [fg.pos newpos], imgsource); - fg.pos = newpos; - fg.newline; - end - - %----------------------------- - function columns(fg, varargin) - %----------------------------- - %COLUMNS Method for dividing input into columns - startpos = fg.pos; - endpos = startpos; - nbrcols = length(varargin); - step = fg.pagewidth / nbrcols; - for i = 1:nbrcols - fg.pos = startpos; - lpos = (i-1)*step; - if iscell(varargin{i}) - for j = 1:length(varargin{i}) - if iscell(varargin{i}{j}) - for k = 1:length(varargin{i}{j}) - feval(varargin{i}{j}{k}, lpos) - end - elseif ~isempty(varargin{i}{j}) - feval(varargin{i}{j}, lpos); - end - end - elseif ~isempty(varargin{i}) - feval(varargin{i}, lpos) - end - endpos = max(fg.pos, endpos); - end - fg.pos = endpos; - - end - - %-------------------------- - function call = newline(fg) - %-------------------------- - %NEWLINE Method to insert a line break - if nargout > 0 - call = @()newline(fg); - return - end - - fg.pos = fg.pos + fg.lineht; - end - - %--------------------------------------------------------- - function newpagepos = pagebreakchk(fg, pagepos, nextblock) - %--------------------------------------------------------- - %PAGEBREAKCHK Method to insert a page break - %Checks if it is time to insert a page break using 'pagepos' parameter - maxpageheight = 1506; %Approximated from studies of some common browser printing defaults - newpos = pagepos + nextblock; - if newpos > maxpageheight - fg.zoom; - fg.start; - fg.lineht=15; - axis equal - set(gcf,'units','normalized','outerposition',[0 0 1 1]) - %xlim([0,1000]) - newpagepos = nextblock; - %axis equal - else - newpagepos = newpos; - end - end - - %---------------- - function stop(fg) - %---------------- - %STOP Save all figures to image files, then close them - fg.zoom; - for i = 1:numel(fg.allfigs) - saveas(fg.allfigs(i),fullfile(fg.pathname,sprintf(fg.filename,i))) - end - close(fg.allfigs) - end - - end - - methods(Access = 'private') - - - end - - methods(Static) - %------------- - function call = conc(varargin) - %------------- - %Concatenate two or more function calls - call = varargin; - end - end - -end \ No newline at end of file diff --git a/source/+reporter/figgenerator.p b/source/+reporter/figgenerator.p new file mode 100644 index 0000000..6e245b0 Binary files /dev/null and b/source/+reporter/figgenerator.p differ diff --git a/source/+reporter/htmlgenerator.m b/source/+reporter/htmlgenerator.m deleted file mode 100644 index 168ee94..0000000 --- a/source/+reporter/htmlgenerator.m +++ /dev/null @@ -1,357 +0,0 @@ -%HTMLGENERATOR Class for generating HTML files - -classdef htmlgenerator - - properties(SetAccess = 'private', Hidden) - filename = ''; - pathname = ''; - fid = []; - title = ''; - pagewidth = 0; - end - - methods - - %------------- - function hg = htmlgenerator(title, pathname, filename, pagewidth) - %------------- - %Constructor - if nargin < 4 - pagewidth = 1024; - if nargin < 3 - filename = [title '.htm']; - if nargin < 2 - pathname = pwd; - end - end - end - hg.title = title; - hg.filename = filename; - hg.pathname = pathname; - hg.pagewidth = pagewidth; - end - - %------------- - function hg = start(hg) - %------------- - %START Method to open the HTML file and write headers - hg.fid = fopen(fullfile(hg.pathname,hg.filename), 'w', 'n', 'UTF-8'); - write(hg, html_header(hg)); - end - - %------------- - function stri = hline(hg) - %------------- - %HLINE Method to write a horizontal line - stri = sprintf('
\n
\n
\n'); - %These methods return a string if asked for output, otherwise write - %to file - - if nargout < 1 - write(hg, stri); - end - end - - %------------- - function stri = table(hg, content, boldcells, width, bgcolors) - %------------- - %TABLE Method to insert a table with content specified by a cell. - if nargin <5 - bgcolors = zeros(size(content)); - if nargin < 4 - width = round(0.625*hg.pagewidth); - if nargin < 3 - boldcells = zeros(size(content)); - if nargin < 2 - myfailed('Too few input arguments.'); - end - end - end - end - tdstring=''; - stri = sprintf('\n', width); - for i = 1:size(content, 1) - stri = [stri sprintf('\n')]; %#ok - for j = 1:size(content, 2) - if bgcolors(i,j) == 2 - tdstring='\n',tdstring, b1, content{i,j}, b2)]; %#ok - end - stri = [stri sprintf('\n')]; %#ok - end - stri = [stri sprintf('
'; - elseif bgcolors(i,j) == 3 - tdstring=''; - elseif bgcolors(i,j) == 4 - tdstring=''; - else - tdstring=''; - end - - if boldcells(i, j) == 2 - b1 = ''; - b2 = ''; - elseif boldcells(i, j) == 3 - b1 = ''; - b2 = ''; - elseif boldcells(i, j) == 4 - b1 = ''; - b2 = ''; - - elseif boldcells(i, j) - b1 = ''; - b2 = ''; - else - b1 = ''; - b2 = ''; - end - stri = [stri sprintf('%s%s%s%s
\n
\n')]; - - if nargout < 1 - write(hg, stri); - end - - end - - %------------- - function stri = box(hg, text, width) - %------------- - %BOX Method to insert a text box - if nargin < 3 - width = hg.pagewidth; - if nargin < 2 - myfailed('Too few input arguments.'); - end - end - stri = sprintf(['\n'... - '\n
\n%s\n
\n'], width, text); - if nargout < 1 - write(hg, stri); - end - end - - %------------- - function stri = headline(hg, headtext, prio) - %------------- - %HEADLINE Method to write a headline in bold - if nargin < 3 - prio = 3; - end - stri = sprintf('%s\n', prio, headtext, prio); - if nargout < 1 - write(hg, stri); - end - end - - %------------- - function stri = text(hg, paragraph, alignment) - %------------- - %TEXT Method to write a paragraph of text - if nargin == 3 - alstr = sprintf(' align=%s',alignment); - else - alstr = ''; - end - stri = sprintf('\n%s\n

\n',alstr,paragraph); - if nargout < 1 - write(hg, stri); - end - end - - %------------ - function gsstri = ftext(hg) - %------------ - %FTEXT Method to write a paragraph of text with formatted headlines. - global SET - stri = []; - gsstri = []; %Gensvar string (unformatted) - cr = []; - prow = 1; %Variable to keep track of row number in current paragraph - %Convert from Matlab string matrix to viewable text - comment = SET(1).Report.Comments; - newlines = [0 regexp(comment,'(\n)') numel(comment)+1]; - for row = 2:numel(newlines) - crprev = cr; - if ~isempty(crprev) - crprev = regexprep(crprev,{'\*','\.'},{'\\*','\\.'}); - end - cr = comment(newlines(row-1)+1:newlines(row)-1); - gsstri = [gsstri cr sprintf('\n')]; %#ok - if isempty(cr) %Insert new paragraph if a line is blank - stri = [stri sprintf('\n

\n

\n')]; %#ok - prow = 1; - else - if prow == 2 %Create headline according to rules of formatting (see manual) - if strcmp(upper(crprev),crprev) - stri = regexprep(stri,crprev,sprintf('

%s

',crprev)); %superheadline - prow = 1; - else - stri = regexprep(stri,crprev,sprintf('

%s

',crprev)); %subheadline - end - elseif prow > 2 - stri = [stri sprintf('
\n')]; %#ok - end - stri = [stri sprintf('%s\n',cr)]; %#ok - prow = prow + 1; - end - end - hg.text(stri); - end - - %------------- - function stri = image(hg, imgname, imgsource) - %------------- - %IMAGE Method to add an image. Also stores it to disk in - % the same folder as the HTML file. imgsource can be a - % location or an image matrix. - - if nargin < 3 - stri = sprintf('\n
\n', imgname); - else - imgdest = [hg.pathname filesep imgname]; - if ischar(imgsource) - try - imgsource = imread(imgsource); - catch me - mydispexception(me); - error('Could not read image file'); - end - end - try - imwrite(imgsource, imgdest); - stri = sprintf('\n
\n', imgname); - catch me - mydispexception(me); - error('Could not write image file'); - end - end - - if nargout < 1 - write(hg, stri); - end - end - - %------------- - function stri = columns(hg, varargin) - %------------- - %COLUMNS Method to insert a table without borders, used for dividing - %input into columns - -% colfunix = [find(cellfun('isclass',varargin,'function_handle'))... -% length(varargin)+1]; -% if isempty(colfunix) -% outargs = varargin; -% else -% nbroffuns = length(colfunix)-1; -% outargs = cell(1,nbroffuns); -% for i = 1:nbroffuns -% inargs = varargin(colfunix(i):colfunix(i+1)-1); -% outargs{i} = feval(inargs{:}); -% end -% end - - stri = sprintf('\n',hg.pagewidth); - for i = 1:length(varargin) - stri = [stri sprintf('\n', varargin{i})]; %#ok - end - stri = [stri sprintf('
%s
\n')]; - - if nargout < 1 - write(hg, stri); - end - end - - %------------- - function stri = link(hg, ref, text) - %------------- - %LINK Method to write a link to a file or URL - if nargin < 3 - text = ref; - end - stri = sprintf('%s\n', ref, text); - - if nargout < 1 - write(hg, stri); - end - end - - %-------------------------- - function stri = newline(hg) - %-------------------------- - %NEWLINE Method to insert a line break - stri = '
'; - if nargout == 0 - write(hg,stri); - end - - end - - %------------- - function newpagepos = pagebreakchk(hg, pagepos, nextblock) - %------------- - %PAGEBREAKCHK Method to insert a page break - %Checks if it is time to insert a page break using 'pagepos' parameter - maxpageheight = 1506; %Approximated from studies of some common browser printing defaults - newpos = pagepos + nextblock; - if newpos > maxpageheight - hg.text('

'); - newpagepos = nextblock; - else - newpagepos = newpos; - end - end - - %------------- - function hg = stop(hg) - %------------- - %STOP Method to write necessary HTML footers and close file - write(hg, html_footer(hg)); - fclose(hg.fid); - end - - end %End of methods - - methods (Access = 'private') - - %------------- - function write(hg, str) - %------------- - %Writes a string of characters to file - fprintf(hg.fid, '%s', str); - end - - %-------------------------- - function stri = html_header(hg) - %-------------------------- - %Return string used as HTML header - stri = []; - - stri = [stri sprintf('\n')]; - stri = [stri sprintf('\n')]; - stri = [stri sprintf('%s\n', hg.title)]; - stri = [stri sprintf('\n')]; - stri = [stri sprintf('\n')]; - stri = [stri sprintf('\n\n')]; - stri = [stri sprintf('\n', hg.pagewidth)]; - - end - - %-------------------------- - function stri = html_footer(hg) %#ok - %-------------------------- - %Return string used as HTML footer - stri = sprintf('\n\n'); - end - - end %End of private methods - - methods(Static) - %------------- - function stri = conc(varargin) - %------------- - %Concatenate two or more function calls - stri = [varargin{:}]; - end - end - -end - \ No newline at end of file diff --git a/source/+reporter/htmlgenerator.p b/source/+reporter/htmlgenerator.p new file mode 100644 index 0000000..b0129d5 Binary files /dev/null and b/source/+reporter/htmlgenerator.p differ diff --git a/source/+reporter/logo.png b/source/+reporter/logo.png deleted file mode 100644 index d0a4ded..0000000 Binary files a/source/+reporter/logo.png and /dev/null differ diff --git a/source/+reporter/pdf2dcm.exe b/source/+reporter/pdf2dcm.exe new file mode 100644 index 0000000..bb87c29 Binary files /dev/null and b/source/+reporter/pdf2dcm.exe differ diff --git a/source/+reporter/reference/buechel_f0018.normvalues.txt b/source/+reporter/reference/buechel_f0018.normvalues.txt new file mode 100644 index 0000000..449f93b --- /dev/null +++ b/source/+reporter/reference/buechel_f0018.normvalues.txt @@ -0,0 +1,17 @@ +Name: 'Buechel, Females, Age 0-18' +ImagingType: 'SSFP' +Sex: 'F' +LowerAgeBound: 0 +UpperAgeBound: 18 +LVM: [(10^(-2*0.0475))*(45.2*(SET(1).PatientInfo.BSA^1.304)) (10^(2*0.0475))*(45.2*(SET(1).PatientInfo.BSA^1.304))] +EDV: [(10^(-2*0.0426))*(67.8*(SET(1).PatientInfo.BSA^1.38)) (10^(2*0.0426))*(67.8*(SET(1).PatientInfo.BSA^1.38))] +ESV: [(10^(-2*0.0647))*(26.1*(SET(1).PatientInfo.BSA^1.37)) (10^(2*0.0647))*(26.1*(SET(1).PatientInfo.BSA^1.37))] +SV: [(10^(-2*0.05))*(41.7*(SET(1).PatientInfo.BSA^1.394)) (10^(2*0.05))*(41.7*(SET(1).PatientInfo.BSA^1.394))] +EF: [(10^(-2*0.041))*61.3 (10^(2*0.041))*61.3] +RVM: [(10^(-2*0.0605))*(14.9*(SET(1).PatientInfo.BSA^1.331)) (10^(2*0.0605))*(14.9*(SET(1).PatientInfo.BSA^1.331))] +RVEDV: [(10^(-2*0.0499))*(72.7*(SET(1).PatientInfo.BSA^1.469)) (10^(2*0.0499))*(72.7*(SET(1).PatientInfo.BSA^1.469))] +RVESV: [(10^(-2*0.0737))*(30.2*(SET(1).PatientInfo.BSA^1.559)) (10^(2*0.0737))*(30.2*(SET(1).PatientInfo.BSA^1.559))] +RVSV: [(10^(-2*0.0524))*(42.1*(SET(1).PatientInfo.BSA^1.407)) (10^(2*0.0524))*(42.1*(SET(1).PatientInfo.BSA^1.407))] +RVEF: [(10^(-2*0.042))*(61.8-(3.6*SET(1).PatientInfo.BSA)) (10^(2*0.042))*(61.8-(3.6*SET(1).PatientInfo.BSA))] +CO: [(10^(-2*0.0727))*(3.622*(SET(1).PatientInfo.BSA^1.062)) (10^(2*0.0727))*(3.622*(SET(1).PatientInfo.BSA^1.062))] +RVCO: [(10^(-2*0.0783))*(3.6583*(SET(1).PatientInfo.BSA^1.076)) (10^(2*0.0783))*(3.6583*(SET(1).PatientInfo.BSA^1.076))] \ No newline at end of file diff --git a/source/+reporter/reference/buechel_m0018.normvalues.txt b/source/+reporter/reference/buechel_m0018.normvalues.txt new file mode 100644 index 0000000..9db5d6a --- /dev/null +++ b/source/+reporter/reference/buechel_m0018.normvalues.txt @@ -0,0 +1,17 @@ +Name: 'Buechel, Males, Age 0-18' +ImagingType: 'SSFP' +Sex: 'M' +LowerAgeBound: 0 +UpperAgeBound: 18 +LVM: [(10^(-2*0.0475))*(53*(SET(1).PatientInfo.BSA^1.304)) (10^(2*0.0475))*(53*(SET(1).PatientInfo.BSA^1.304))] +EDV: [(10^(-2*0.0426))*(77.5*(SET(1).PatientInfo.BSA^1.38)) (10^(2*0.0426))*(77.5*(SET(1).PatientInfo.BSA^1.38))] +ESV: [(10^(-2*0.0647))*(29.7*(SET(1).PatientInfo.BSA^1.37)) (10^(2*0.0647))*(29.7*(SET(1).PatientInfo.BSA^1.37))] +SV: [(10^(-2*0.05))*(47.4*(SET(1).PatientInfo.BSA^1.394)) (10^(2*0.05))*(47.4*(SET(1).PatientInfo.BSA^1.394))] +EF: [(10^(-2*0.041))*61.3 (10^(2*0.041))*61.3] +RVM: [(10^(-2*0.0605))*(16.7*(SET(1).PatientInfo.BSA^1.331)) (10^(2*0.0605))*(16.7*(SET(1).PatientInfo.BSA^1.331))] +RVEDV: [(10^(-2*0.0499))*(83.8*(SET(1).PatientInfo.BSA^1.469)) (10^(2*0.0499))*(83.8*(SET(1).PatientInfo.BSA^1.469))] +RVESV: [(10^(-2*0.0737))*(35.3*(SET(1).PatientInfo.BSA^1.559)) (10^(2*0.0737))*(35.3*(SET(1).PatientInfo.BSA^1.559))] +RVSV: [(10^(-2*0.0524))*(48.2*(SET(1).PatientInfo.BSA^1.407)) (10^(2*0.0524))*(48.2*(SET(1).PatientInfo.BSA^1.407))] +RVEF: [(10^(-2*0.042))*(61.8-(3.6*SET(1).PatientInfo.BSA)) (10^(2*0.042))*(61.8-(3.6*SET(1).PatientInfo.BSA))] +CO: [(10^(-2*0.0727))*(3.89*(SET(1).PatientInfo.BSA^1.062)) (10^(2*0.0727))*(3.89*(SET(1).PatientInfo.BSA^1.062))] +RVCO: [(10^(-2*0.0783))*(3.9473*(SET(1).PatientInfo.BSA^1.076)) (10^(2*0.0783))*(3.9473*(SET(1).PatientInfo.BSA^1.076))] \ No newline at end of file diff --git a/source/+reporter/report2clipboard.p b/source/+reporter/report2clipboard.p new file mode 100644 index 0000000..6c66752 Binary files /dev/null and b/source/+reporter/report2clipboard.p differ diff --git a/source/+reporter/reportgenerator.p b/source/+reporter/reportgenerator.p new file mode 100644 index 0000000..ef30ec0 Binary files /dev/null and b/source/+reporter/reportgenerator.p differ diff --git a/source/+reporter/reportsheet.fig b/source/+reporter/reportsheet.fig index 028f491..4a1aecd 100644 Binary files a/source/+reporter/reportsheet.fig and b/source/+reporter/reportsheet.fig differ diff --git a/source/+reporter/reportsheet.p b/source/+reporter/reportsheet.p index 1edf09d..3e8308d 100644 Binary files a/source/+reporter/reportsheet.p and b/source/+reporter/reportsheet.p differ diff --git a/source/+reporter/sendtogensvar.m b/source/+reporter/sendtogensvar.m deleted file mode 100644 index 7f9a0b6..0000000 --- a/source/+reporter/sendtogensvar.m +++ /dev/null @@ -1,39 +0,0 @@ -function resulturl = sendtogensvar(url, username, password, data) - % This function creates a study in gensvar and returns the url of the - % study. For a list of valid fieldnames in the data structure see - % the function getStudyFieldGroup() in common.php. - - % Prepare data - fnames = fieldnames(data); - sdata = {}; - for i=1:numel(fnames) - value = data.(fnames{i}); - if isa(value, 'char') - sdata = [sdata {fnames{i}} {value}]; - continue - end - if isa(value, 'double') || isa(value, 'single') - sdata = [sdata {fnames{i}} {sprintf('%f', value)}]; - continue - end - error('SEGMENT:ERROR', 'Bad value type in data parameter'); - end - - % Send - rr = urlread([url '/api.php'], 'POST', [{'action', 'create_study', 'username', username, 'password', password} sdata]); - r = regexp(rr, '\n', 'split'); - if(not(isequal(r{1}, 'gensvar'))) - error('SEGMENT:ERROR', ['Couldn''t connect to gensvar: ' rr]); - end - if(isequal(r{2}, 'ok')) - resulturl = [url '/editstudy.php?id=' r{3}]; - return - end - if(isequal(r{2}, 'noaccess')) - error('SEGMENT:ERROR', 'Bad combination of username and password'); - end - if(isequal(r{2}, 'baddata')) - error('SEGMENT:ERROR', ['Bad data sent. Gensvar says: ''' r{3} '''.']); - end - error('SEGMENT:ERROR', 'Unknown result sent from gensvar'); -end \ No newline at end of file diff --git a/source/+reporter/sendtogensvar.p b/source/+reporter/sendtogensvar.p new file mode 100644 index 0000000..a0e3f7f Binary files /dev/null and b/source/+reporter/sendtogensvar.p differ diff --git a/source/+segment3dp/tools.m b/source/+segment3dp/tools.m new file mode 100644 index 0000000..a10cdb3 --- /dev/null +++ b/source/+segment3dp/tools.m @@ -0,0 +1 @@ +function varargout = tools(varargin) diff --git a/source/+spect/autoperfusionspect.m b/source/+spect/autoperfusionspect.m index 44e85a0..486caf1 100644 --- a/source/+spect/autoperfusionspect.m +++ b/source/+spect/autoperfusionspect.m @@ -13,7 +13,7 @@ pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; end %find the .mat files @@ -92,12 +92,7 @@ if doanalysis for loop = 1:length(SET) SET(loop).Linked = loop; - segment('switchtoimagestack',loop); - DATA.ViewPanels(1) = NO; - DATA.ViewIM{1} = []; - DATA.Overlay(1) = struct('alphadata', [], 'cdata', []); - drawfunctions('drawimageno',NO); - DATA.switchtoimagestack(NO,true); %force + viewfunctions('setview',1,1,NO,{'one'}) tools('setcolormap_Callback','spect'); if SET(NO).ResolutionX > 4 tools('upsampleimage_Callback',2); @@ -147,17 +142,8 @@ end end -% spect.spectperfusionsegmentation('perfusionanalyze_Callback',0); - %viewing -% segment('viewallimagestacks_Callback'); -% for j = 1:length(SET) -% segment('switchtoimagestack',j); -% DATA.switchtoimagestack(NO,true); %force -% DATA.CurrentPanel = j; -% segment('viewimage_Callback','montage'); -% segment('viewrefresh_Callback'); -% end - segment('viewrefreshall_Callback'); + viewfunctions('setview') + %saving file DATA.Buffer.KeyStroke = {'ok'}; %Put ok in queue for confirm box. filemenu('saveall_Callback') diff --git a/source/+spect/spectlvsegmentation.p b/source/+spect/spectlvsegmentation.p index 3ac2f3f..e27fcad 100644 Binary files a/source/+spect/spectlvsegmentation.p and b/source/+spect/spectlvsegmentation.p differ diff --git a/source/+spect/spectmarsegmentation.p b/source/+spect/spectmarsegmentation.p index 7aa748c..db821f5 100644 Binary files a/source/+spect/spectmarsegmentation.p and b/source/+spect/spectmarsegmentation.p differ diff --git a/source/+spect/spectperfusionsegmentation.p b/source/+spect/spectperfusionsegmentation.p index e8d3534..d0f786d 100644 Binary files a/source/+spect/spectperfusionsegmentation.p and b/source/+spect/spectperfusionsegmentation.p differ diff --git a/source/+spect/spectplot2d.fig b/source/+spect/spectplot2d.fig index 4d62f4c..dbc6f31 100644 Binary files a/source/+spect/spectplot2d.fig and b/source/+spect/spectplot2d.fig differ diff --git a/source/+spect/spectplot2d.m b/source/+spect/spectplot2d.m index 9da59e2..409a796 100644 --- a/source/+spect/spectplot2d.m +++ b/source/+spect/spectplot2d.m @@ -65,7 +65,7 @@ function init_Callback(mode,makeviewmode) nos.stressgated = stressgatedno; fnames = fieldnames(nos); -h = mywaitbarstart(3,'Calculating',1,DATA.GUI.Segment); +h = mywaitbarstart(5,'Calculating',1,DATA.GUI.Segment); IM = []; LVsegmentation = []; @@ -189,7 +189,8 @@ function init_Callback(mode,makeviewmode) VLAslice.(field),LVsegmentation.(field),EndoX.(field), ... EndoY.(field),EpiX.(field),EpiY.(field), startslices.(field), ... endslices.(field),isLVseg.(field),tnbr,mode,resamplexy.(field)); - end + end + h = mywaitbarupdate(h); end mywaitbarclose(h); @@ -718,7 +719,7 @@ function init_Callback(mode,makeviewmode) end %upsample images spatially IM = tools('upsampleslices',fsz,IM,1); - IM = tools('upsamplevolume',fs,IM,1); + IM = tools('upsamplevolume2',[fs fs 1 1],IM,1); %upsample images temporally if ft ~= 1 IM = tools('upsampletemporal',ft,IM); @@ -1247,7 +1248,12 @@ function init_Callback(mode,makeviewmode) switch gui.showimagetype{1} case {'stress','stressgated','restgated'} + colormap(gui.handles.axesSAapicalleft,'spect'); colormap(gui.handles.axesSAmidleft,'spect'); + colormap(gui.handles.axesSAbasalleft,'spect'); + colormap(gui.handles.axesHLAleft,'spect'); + colormap(gui.handles.axesVLAleft,'spect'); + axis(gui.handles.axesSAbasalleft,'image','off'); set(gui.handles.axesSAbasalleft,'clim',[normmincount normmaxcount]); axis(gui.handles.axesSAmidleft,'image','off'); @@ -1345,7 +1351,11 @@ function init_Callback(mode,makeviewmode) end switch gui.showimagetype{2} case {'rest','restgated'} + colormap(gui.handles.axesSAapicalright,'spect'); colormap(gui.handles.axesSAmidright,'spect'); + colormap(gui.handles.axesSAbasalright,'spect'); + colormap(gui.handles.axesHLAright,'spect'); + colormap(gui.handles.axesVLAright,'spect'); axis(gui.handles.axesSAbasalright,'image','off'); set(gui.handles.axesSAbasalright,'clim',[normmincount normmaxcount]); axis(gui.handles.axesSAmidright,'image','off'); @@ -1916,7 +1926,7 @@ function plotahavalues(panel) SRS = SRS+gui.scoringvalues{3,loop}; end set(gui.handles.textScoring,'String',['SRS: ',num2str(SRS)]); - scoringexplanation = sprintf('%s\n%s\n%s\n%s','Scoring of presence of infarct','0: normal','1: equivocal','2: infarct'); + scoringexplanation = sprintf('%s\n%s\n%s\n%s\n%s\n%s','Scoring of presence of infarct','0: normal','1: equivocal','2: moderate','3: severe infact','4: apparent infact'); set(gui.handles.textScoringExplanation,'String',scoringexplanation); case 0 for loop = 1:size(gui.scoringvalues,2) @@ -2220,6 +2230,11 @@ function plotSAintersections(panel) set(gui.handles.textVLAleft,'String',[]); set(gui.handles.textleft,'String',[]); end + colormap(gui.handles.axesSAapicalleft,'spect'); + colormap(gui.handles.axesSAmidleft,'spect'); + colormap(gui.handles.axesSAbasalleft,'spect'); + colormap(gui.handles.axesHLAleft,'spect'); + colormap(gui.handles.axesVLAleft,'spect'); else %no images to plot set(gui.handles.axesSAbasalimageleft,'cdata',[]); @@ -3241,8 +3256,8 @@ function hideSAintersections(panel) if get(gui.handles.radiobuttonshowsegmentation,'value') updateLVsegmentation; if isequal(gui.mode,'scoring') - updateahasections('both'); - hideSAintersections('both'); + updateahasections('both'); + updateSAintersections('left'); end end if isequal(gui.mode,'scoring') @@ -3524,8 +3539,8 @@ function roundtf(roundmethod) succeed = false; return; end - if isempty(gui.scoringvalues{3,k}) || ~isnumeric(gui.scoringvalues{3,k}) || gui.scoringvalues{3,k}<0 || gui.scoringvalues{3,k}>2 - myfailed('REST Infarct: Scoring value missing, or outside the allowed range [0 2]'); + if isempty(gui.scoringvalues{3,k}) || ~isnumeric(gui.scoringvalues{3,k}) || gui.scoringvalues{3,k}<0 || gui.scoringvalues{3,k}>4 + myfailed('REST Infarct: Scoring value missing, or outside the allowed range [0 4]'); succeed = false; return; end @@ -4534,6 +4549,7 @@ function keypressed(fignum,evnt) %#ok SDS = 0; pos = [17 13 16:-1:14 7 12:-1:8 1 6:-1:2]; +if isequal(currentobj.Style,'edit') if get(gui.handles.radiobuttongated,'value') tags = {'editHLAright', ... 'editapicalantright','editapicallatright', ... @@ -4578,6 +4594,7 @@ function keypressed(fignum,evnt) %#ok scoringvalues = sprintf('%s\n%s\n%s',['SSS: ',num2str(SSS)],['SRS: ',num2str(SRS)],['SDS: ',num2str(SDS)]); set(gui.handles.textScoring,'String',scoringvalues); end +end %--------------------------------------------------------------------- function lvv = calclvv(startslices,endslices,endox,endoy,t,resXY,resZ) diff --git a/source/+spect/spectregistration.p b/source/+spect/spectregistration.p index aa70747..379cab1 100644 Binary files a/source/+spect/spectregistration.p and b/source/+spect/spectregistration.p differ diff --git a/source/+spect/spectsplinetoolsC.mexw32 b/source/+spect/spectsplinetoolsC.mexw32 deleted file mode 100644 index cc98cce..0000000 Binary files a/source/+spect/spectsplinetoolsC.mexw32 and /dev/null differ diff --git a/source/+strain/strain.fig b/source/+strain/strain.fig deleted file mode 100644 index 48e9aca..0000000 Binary files a/source/+strain/strain.fig and /dev/null differ diff --git a/source/+strain/strain.p b/source/+strain/strain.p deleted file mode 100644 index f4dc7fd..0000000 Binary files a/source/+strain/strain.p and /dev/null differ diff --git a/source/+straintagging/CardiacMotion32.exe b/source/+straintagging/CardiacMotion32.exe deleted file mode 100644 index 5d26a7f..0000000 Binary files a/source/+straintagging/CardiacMotion32.exe and /dev/null differ diff --git a/source/+straintagging/LAXselectslices.m b/source/+straintagging/LAXselectslices.m index 29b7330..76385e6 100644 --- a/source/+straintagging/LAXselectslices.m +++ b/source/+straintagging/LAXselectslices.m @@ -65,7 +65,8 @@ function init(taggroup) %#ok case '2CH' axh(tagno)=gui.handles.LAX2CH_axes; colormap(axh(tagno),gray(255)); - gui.handles.im2CH=imshow(twochamber,'Parent',axh(tagno)); + gui.handles.im2CH=image(cat(3,twochamber,twochamber,twochamber),'Parent',axh(tagno)); + axis(axh(tagno),'off','image') hold(axh(tagno), 'on') set(axh(tagno),'plotboxaspectratio',[max(zsz)*... ysz(tagno)*yres(tagno) xsz(tagno)*xres(tagno) 1]); @@ -75,7 +76,8 @@ function init(taggroup) %#ok case '3CH' axh(tagno)=gui.handles.LAX3CH_axes; colormap(axh(tagno),gray(255)); - gui.handles.im3CH=imshow(threechamber,'Parent',axh(tagno)); + gui.handles.im3CH=image(cat(3,threechamber,threechamber,threechamber),'Parent',axh(tagno)); + axis(axh(tagno),'off','image') hold(axh(tagno), 'on') set(axh(tagno),'plotboxaspectratio',[max(zsz)*... ysz(tagno)*yres(tagno) xsz(tagno)*xres(tagno) 1]); @@ -85,7 +87,8 @@ function init(taggroup) %#ok case '4CH' axh(tagno)=gui.handles.LAX4CH_axes; colormap(axh(tagno),gray(255)); - gui.handles.im4CH=imshow(fourchamber,'Parent',axh(tagno)); + gui.handles.im4CH=image(cat(3,fourchamber,fourchamber,fourchamber),'Parent',axh(tagno)); + axis(axh(tagno),'off','image') hold(axh(tagno), 'on') set(axh(tagno),'plotboxaspectratio',[max(zsz)*... ysz(tagno)*yres(tagno) xsz(tagno)*xres(tagno) 1]); @@ -128,14 +131,30 @@ function init(taggroup) %#ok %------------------- %generates new stack then terminates the gui and start strain analysis -global DATA +global DATA SET gui=DATA.GUI.LAXselectslices; taggroup=gui.taggroup; -strainno=LAXgenerateimagestack(taggroup); +strainno=LAXgenerateimagestack(taggroup); %generates new image stacks + +%correct the taggroup, should be in order 2CH, 3CH, 4CH as they exist + +%find order for 2CH, 3CH, 4CH +chamberexist(1,:)=strcmp('2CH',{SET.ImageViewPlane}); +chamberexist(2,:)=strcmp('3CH',{SET.ImageViewPlane}); +chamberexist(3,:)=strcmp('4CH',{SET.ImageViewPlane}); +taggroupnew = []; +for chloop = 1:3 + taggroupnew = [taggroupnew find(chamberexist(chloop,:))]; +end +straingroup = strainno; +straingroup(isnan(strainno)) = taggroup(isnan(strainno)); +for noloop = straingroup + SET(noloop).StrainTagging.taggroup = taggroupnew; +end close_callback; -straintagging.straintagging('init','cine','longaxis'); +straintagging.straintagging('init','cine','longaxis',straingroup(1)); %---------------------- function close_callback @@ -151,10 +170,12 @@ function init(taggroup) %#ok end %---------------------------------- -function strainno=LAXgenerateimagestack(taggroup) +function strainnoall=LAXgenerateimagestack(taggroup) %---------------------------------- global DATA SET gui=DATA.GUI.LAXselectslices; +strainnoall = []; +ind = 1; for tagno=taggroup if SET(tagno).ZSize>1 @@ -219,6 +240,7 @@ function init(taggroup) %#ok strainno = numel(SET)+1; SET(strainno) = laxset; SET(strainno).KeptSlices = gui.slicestouse{tagno}; + strainnoall(ind) = strainno; %Change some descriptors in previous making obscured for strain %analysis @@ -226,15 +248,13 @@ function init(taggroup) %#ok SET(tagno).ImageViewPlane='Unspecified'; %draw new image stack and update volumes - DATA.switchtoimagestack(strainno); - segment_main('viewimage_Callback','montage'); + viewfunctions('setview',1,1,strainno,{'montage'}) drawfunctions('drawthumbnails'); - drawfunctions('drawallslices'); - drawfunctions('drawimageno'); segment_main('updatevolume'); - segment_main('updatemodeldisplay'); - updatetool('select'); + else + strainnoall(ind) = NaN; end + ind = ind+1; end %----------------------------------------- diff --git a/source/+straintagging/cm_readMhdData.p b/source/+straintagging/cm_readMhdData.p index befcb25..672c26c 100644 Binary files a/source/+straintagging/cm_readMhdData.p and b/source/+straintagging/cm_readMhdData.p differ diff --git a/source/+straintagging/cm_readVTKData.p b/source/+straintagging/cm_readVTKData.p index c496640..b2191df 100644 Binary files a/source/+straintagging/cm_readVTKData.p and b/source/+straintagging/cm_readVTKData.p differ diff --git a/source/+straintagging/cm_writeMhdData.p b/source/+straintagging/cm_writeMhdData.p index 021939c..aae5389 100644 Binary files a/source/+straintagging/cm_writeMhdData.p and b/source/+straintagging/cm_writeMhdData.p differ diff --git a/source/+straintagging/cm_writeVTKData.p b/source/+straintagging/cm_writeVTKData.p index 4c14aa2..83c0218 100644 Binary files a/source/+straintagging/cm_writeVTKData.p and b/source/+straintagging/cm_writeVTKData.p differ diff --git a/source/+straintagging/cropstraintagging.fig b/source/+straintagging/cropstraintagging.fig index ae86150..2bcfe58 100644 Binary files a/source/+straintagging/cropstraintagging.fig and b/source/+straintagging/cropstraintagging.fig differ diff --git a/source/+straintagging/cropstraintagging.m b/source/+straintagging/cropstraintagging.m index 9d3d81b..e12f1c3 100644 --- a/source/+straintagging/cropstraintagging.m +++ b/source/+straintagging/cropstraintagging.m @@ -27,7 +27,7 @@ end end -gui = mygui(['straintagging' filesep 'cropstraintagging.fig']); +gui = mygui(['+straintagging' filesep 'cropstraintagging.fig']); DATA.GUI.CropStrainTagging = gui; gui.state = false; diff --git a/source/+straintagging/drawguide.fig b/source/+straintagging/drawguide.fig index 420086e..fed0e09 100644 Binary files a/source/+straintagging/drawguide.fig and b/source/+straintagging/drawguide.fig differ diff --git a/source/+straintagging/dyssynchrony.fig b/source/+straintagging/dyssynchrony.fig index 764acd9..755cb54 100644 Binary files a/source/+straintagging/dyssynchrony.fig and b/source/+straintagging/dyssynchrony.fig differ diff --git a/source/+straintagging/dyssynchrony.m b/source/+straintagging/dyssynchrony.m index afa585a..fbdbff2 100644 --- a/source/+straintagging/dyssynchrony.m +++ b/source/+straintagging/dyssynchrony.m @@ -34,7 +34,11 @@ function init(taggroup,type) .5 .5 0]; if strcmp(type,'LAX') - set(gui.handles.typepopupmenu,'String',{'Longitudinal Peak Time';'Longitudinal Strain';'Radial Peak Time';'Radial Strain'}) + set(gui.handles.typepopupmenu,'String',{... + dprintf('Longitudinal Peak Time');... + dprintf('Longitudinal Strain');... + dprintf('Radial Peak Time');... + dprintf('Radial Strain')}) include2ch=0; include3ch=0; include4ch=0; @@ -91,7 +95,11 @@ function init(taggroup,type) end else - set(gui.handles.typepopupmenu,'String',{'Circumferential Peak Time';'Circumferential Strain';'Radial Peak Time';'Radial Strain'}) + set(gui.handles.typepopupmenu,'String',{... + dprintf('Circumferential Peak Time');... + dprintf('Circumferential Strain');... + dprintf('Radial Peak Time');... + dprintf('Radial Strain')}) no=taggroup; T=SET(no).TSize; @@ -585,10 +593,11 @@ function setpeakbuttonup(type,handleind)%#ok %type,ind) strlist=get(gui.handles.typepopupmenu,'String'); ind=get(gui.handles.typepopupmenu,'Value'); str=strlist{ind}; +engstr = translation.dictionary(str,'English',DATA.Pref.Language); %ensure that it is English hold(h,'on') grid(h,'on'); -switch str +switch engstr case {'Circumferential Peak Time','Longitudinal Peak Time'} set(h,'Ydir','reverse') for i=gui.sections2show%1:17 @@ -598,7 +607,7 @@ function setpeakbuttonup(type,handleind)%#ok %type,ind) set(h,'ytick',1:17) set(h,'yticklabel',ahastri(pos)) ylim(h,[0,18]) - legend(h,gui.handles.cumplabel,'Cumulative strain peak') + legend(h,gui.handles.cumplabel,dprintf('Cumulative strain peak')) ylabel(h,'') case 'Radial Peak Time' @@ -610,7 +619,7 @@ function setpeakbuttonup(type,handleind)%#ok %type,ind) set(h,'ytick',1:17) set(h,'yticklabel',ahastri(pos)) ylim(h,[0,18]) - legend(h,gui.handles.cumplabel,'Cumulative strain peak') + legend(h,gui.handles.cumplabel,dprintf('Cumulative strain peak')) ylabel(h,'') case {'Circumferential Strain','Longitudinal Strain'} @@ -638,7 +647,7 @@ function setpeakbuttonup(type,handleind)%#ok %type,ind) xlim(h,[0,gui.tvec(end)]) ylabel(h,'%') end -xlabel(h,'Heart Cycle [s/T]') +xlabel(h,dprintf('Heart Cycle [s/T]')) hold(h,'off') diff --git a/source/+straintagging/runexe.p b/source/+straintagging/runexe.p index 9fc23b1..8a9ab16 100644 Binary files a/source/+straintagging/runexe.p and b/source/+straintagging/runexe.p differ diff --git a/source/+straintagging/strain.fig b/source/+straintagging/strain.fig index 6303c15..1218cde 100644 Binary files a/source/+straintagging/strain.fig and b/source/+straintagging/strain.fig differ diff --git a/source/+straintagging/strainrate.fig b/source/+straintagging/strainrate.fig index ab783d1..260641b 100644 Binary files a/source/+straintagging/strainrate.fig and b/source/+straintagging/strainrate.fig differ diff --git a/source/+straintagging/strainrate.m b/source/+straintagging/strainrate.m deleted file mode 100644 index 4616b87..0000000 --- a/source/+straintagging/strainrate.m +++ /dev/null @@ -1,1092 +0,0 @@ -function varargout = strainrate(varargin) -%Gives strainrate measures - -macro_helper(varargin{:}); -[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard - - -%--------------------------------------- -function init(taggroup,type) -%---------------------------------------- -global SET DATA - -gui = mygui(fullfile('+straintagging','strainrate.fig')); -DATA.GUI.strainrate = gui; -if strcmp(type,'LAX') - taggrouptmp=nan(1,3); - %sort taggroup so we can always use gui.views2show for indexes in LAX - for tagno=taggroup - switch SET(tagno).ImageViewPlane - case '2CH' - taggrouptmp(1)=tagno; - case '3CH' - taggrouptmp(2)=tagno; - case '4CH' - taggrouptmp(3)=tagno; - end - end - taggrouptmp(isnan(taggrouptmp))=[]; - taggroup=taggrouptmp; - gui.taggroup=taggroup; -else - gui.taggroup=taggroup; -end -gui.oneatatime=0; -gui.lastpressed=[]; -gui.tvec = SET(taggroup(1)).StrainTagging.strainrateTvect; -gui.cmap=[1 1 0;... - 0 0 1;... - 0 1 0;... - 0 1 1;... - 1 0 0;... - 1 0 1;... - .5 .5 0;... - .8 .8 .8;... - 240/255 120/255 0;... - 64/255 0 128/255;... - 128/255 64/255 0;... - 0 64/255 0;... - 128/255 128/255 128/255;... - 128/255 128/255 1;... - 0 128/255 128/255;... - 128/255 0 0;... - 1 128/255 128/255]; - -srstack=[]; -for no = taggroup - if isfield(SET(no).StrainTagging,'SR') - srstack=no; - break; - end -end - -if isempty(srstack) %|| isfield(SET(no).StrainTagging.SR,'updated') - tmpstruct = calcstrainrate(type, taggroup); -else - tmpstruct=SET(srstack).StrainTagging.SR; -end - -%combine structs - f = fieldnames(tmpstruct); - for i = 1:length(f) - gui.(f{i}) = tmpstruct.(f{i}); - end - -switch type - case 'LAX' - - %gui.tvec = %linspace(0,1,SET(taggroup(1)).TSize-2); - strcell={'2CH','3CH','4CH'}; - gui.radios2show =1:sum(gui.include);%1:length(taggroup); - set(gui.handles.typepopupmenu ,'String',{'Longitudinal Strain Rate';... - 'Radial Strain Rate';... - 'Mean Longitudinal Strain Rate';... - 'Mean Radial Strain Rate';... - 'Mean Longitudinal Strain with Tangents';... - 'Mean Radial Strain with Tangents';... - 'Longitudinal Strain with Tangents';... - 'Radial Strain with Tangents'}); - used=find(gui.include); - for i=gui.radios2show - set(gui.handles.(['radiobutton',num2str(i)]),'String',strcell{used(i)}); - set(gui.handles.(['radiobutton',num2str(i)]),'Value',1); - set(gui.handles.(['radiobutton',num2str(i)]),'backgroundcolor',gui.cmap(i,:)) - end -% for i=1:length(gui.include)%gui.radios2show -% set(gui.handles.(['radiobutton',num2str(i)]),'Value',1); -% set(gui.handles.(['radiobutton',num2str(i)]),'backgroundcolor',gui.cmap(i,:)) -% end - set(gui.handles.circtext,'String','Longit. [%/s]'); - - set(gui.handles.globalcirctext,'String','Longit. [%/(s/T)]'); - set(gui.handles.globalradtext,'String','Rad. [%/(s/T)]'); - case 'SAX' - - %graphical - set(gui.handles.typepopupmenu ,'String',{'Circumferential Strain Rate';... - 'Radial Strain Rate';... - 'Mean Circumferential Strain Rate';... - 'Mean Radial Strain Rate';... - 'Mean Circumferential Strain with Tangents';... - 'Mean Radial Strain with Tangents';... - 'Circumferential Strain with Tangents';... - 'Radial Strain with Tangents'}); - usedslices=find(gui.include); - gui.radios2show=1:length(usedslices); - for i=gui.radios2show - set(gui.handles.(['radiobutton',num2str(i)]),'Value',1); - set(gui.handles.(['radiobutton',num2str(i)]),'String',sprintf('Slice %d',usedslices(i))) - set(gui.handles.(['radiobutton',num2str(i)]),'backgroundcolor',gui.cmap(i,:)) - end - - set(gui.handles.circtext,'String','Circ. [%/s]'); - - set(gui.handles.globalcirctext,'String','Circ. [%/s]'); - set(gui.handles.globalradtext,'String','Rad. [%/s]'); - set(gui.handles.autoviewpeakpushbutton, 'String','Auto Detect Slice Peaks') -end - -%graphical -for r = gui.radios2show(end)+1:17 - set(gui.handles.(['radiobutton' num2str(r)]),'visible', 'off') - set(gui.handles.(['text' num2str(r)]),'visible', 'off') - set(gui.handles.(['text' num2str(17+r)]),'visible', 'off') - set(gui.handles.(['text' num2str(2*17+r)]),'visible', 'off') - set(gui.handles.(['text' num2str(3*17+r)]),'visible', 'off') -end - -% gui.popupind=get(gui.handles.typepopupmenu,'Value'); - -radio_Callback; - -%-------------------------------------------------------------- -function resetpeaks_Callback(type) -%-------------------------------------------------------------- -global DATA - -gui=DATA.GUI.strainrate; - -switch type - case 'global' - [gui.globalradup, gui.globalradupind] = max(gui.globalsrrad); - [gui.globalraddown, gui.globalraddownind] = min(gui.globalsrrad); - [gui.globalcircup, gui.globalcircupind] = max(gui.globalsrcirc); - [gui.globalcircdown, gui.globalcircdownind] = min(gui.globalsrcirc); - case 'views' - [gui.radup, gui.radupind] = max(gui.srrad,[],2); - [gui.raddown, gui.raddownind] = min(gui.srrad,[],2); - [gui.circup, gui.circupind] = max(gui.srcirc,[],2); - [gui.circdown, gui.circdownind] = min(gui.srcirc,[],2); -end - -updateplot - - -%--------------------------------------------------------------- -function [sr] = calcstrainrate(type, taggroup) -%--------------------------------------------------------------- -%Calculates strainrate from stack group -global SET - - -switch type - case 'LAX' - sz=[3, SET(taggroup(1)).TSize-2]; - sr.srcirc =nan(sz); - sr.srrad = nan(sz); - sr.include=zeros(1,3); - for i = 1:length(taggroup) - switch SET(taggroup(i)).ImageViewPlane - case '2CH' - if ~all(all(isnan(SET(taggroup(i)).StrainTagging.strainratecircum))) - sr.srcirc(1,:) = squeeze(nanmean(SET(taggroup(i)).StrainTagging.strainratecircum,2)); - sr.srrad(1,:) = squeeze(nanmean(SET(taggroup(i)).StrainTagging.strainraterad,2)); - sr.include(1)=1; - else - sr.include(1)=0; - end - case '3CH' - if ~all(all(isnan(SET(taggroup(i)).StrainTagging.strainratecircum))) - sr.srcirc(end-1,:) = squeeze(nanmean(SET(taggroup(i)).StrainTagging.strainratecircum,2)); - sr.srrad(end-1,:) = squeeze(nanmean(SET(taggroup(i)).StrainTagging.strainraterad,2)); - sr.include(2)=1; - else - sr.include(2)=0; - end - case '4CH' - if ~all(all(isnan(SET(taggroup(i)).StrainTagging.strainratecircum))) - sr.srcirc(end,:) = squeeze(nanmean(SET(taggroup(i)).StrainTagging.strainratecircum,2)); - sr.srrad(end,:) = squeeze(nanmean(SET(taggroup(i)).StrainTagging.strainraterad,2)); - sr.include(3)=1; - else - sr.include(3)=0; - end - end - end - sr.srcirc=sr.srcirc(find(sr.include),:); - sr.srrad=sr.srrad(find(sr.include),:); - - case 'SAX' - sr.srcirc = squeeze(nanmean(SET(taggroup(1)).StrainTagging.strainratecircum,2))'; - sr.srrad = squeeze(nanmean(SET(taggroup(1)).StrainTagging.strainraterad,2))'; - - tmp1=[]; - tmp2=[]; - sr.include=ones(1,SET(taggroup(1)).ZSize); - for i = 1:SET(taggroup(1)).ZSize - if ~all(isnan(sr.srcirc(i,2:end))) - tmp1=[tmp1;sr.srcirc(i,:)]; - tmp2=[tmp2;sr.srrad(i,:)]; - else - sr.include(i)=0; - end - end - sr.srcirc=tmp1; - sr.srrad=tmp2; -end - -%Global Strain - if strcmp(SET(taggroup(1)).ImageViewPlane,'Short-axis') - sr.globalsrrad = nanmean(sr.srrad,1); - sr.globalsrcirc = nanmean(sr.srcirc,1); - else - %global strainrate normalised if LAX images - normstrainratecirc=[]; - normstrainraterad =[]; - - for tagno = taggroup - normstrainratecirc = [normstrainratecirc, conv2([1 0 -1],1,SET(tagno).StrainTagging.globalcirc,'valid')/(2/(SET(tagno).TSize-1))]; - normstrainraterad = [normstrainraterad, conv2([1 0 -1],1,SET(tagno).StrainTagging.globalrad,'valid')/(2/(SET(tagno).TSize-1))]; - end - - sr.globalsrcirc=nanmean(normstrainratecirc,2); - sr.globalsrrad=nanmean(normstrainraterad,2); - end - - [sr.globalradup, sr.globalradupind] = max(sr.globalsrrad); - [sr.globalraddown, sr.globalraddownind] = min(sr.globalsrrad); - [sr.globalcircup, sr.globalcircupind] = max(sr.globalsrcirc); - [sr.globalcircdown, sr.globalcircdownind] = min(sr.globalsrcirc); - -[sr.radup, sr.radupind] = max(sr.srrad,[],2); -[sr.raddown, sr.raddownind] = min(sr.srrad,[],2); -[sr.circup, sr.circupind] = max(sr.srcirc,[],2); -[sr.circdown, sr.circdownind] = min(sr.srcirc,[],2); - -%--------------------------------------------------------------- -function setpeak_Callback(type,dir) -%-------------------------------------------------------------- -global DATA -gui = DATA.GUI.strainrate ; -h=gui.handles.segaxes; - -if nargin < 2 - switch type - case 'circ' - tmp=[gui.handles.peakscircup,gui.handles.peakscircdown]; - case 'rad' - tmp=[gui.handles.peaksradup,gui.handles.peaksraddown]; - case 'globalcirc' - tmp=[gui.handles.globalpeakcircup,gui.handles.globalpeakcircdown]; - case 'globalrad' - tmp=[gui.handles.globalpeakradup,gui.handles.globalpeakraddown]; - end - - if ~any(strcmp(type,{'globalrad','globalcirc'})) - x=nan(1,gui.radios2show(end)*2); - y=nan(1,gui.radios2show(end)*2); - - for i = [gui.views2show,gui.views2show+gui.radios2show(end)] - x(i)=get(tmp(i),'Xdata'); - y(i)=get(tmp(i),'Ydata'); - end - - [xclick,yclick]=mygetcurrentpoint(h); - [~,ind]=min((xclick-x).^2+(yclick-y).^2); - - if ind<=gui.radios2show(end) - dir='up'; - else - dir='down'; - end - else - for i = 1:2 - x(i)=get(tmp(i),'Xdata'); - y(i)=get(tmp(i),'Ydata'); - end - - [xclick,yclick]=mygetcurrentpoint(h); - [~,ind]=min((xclick-x).^2+(yclick-y).^2); - - if ind==1 - dir = 'up'; - else - dir = 'down'; - end - end -end - - - switch type - case 'circ' - switch dir - case 'up' - peakhandle=gui.handles.peakscircup; - case 'down' - peakhandle=gui.handles.peakscircdown; - end - case 'rad' - switch dir - case 'up' - peakhandle=gui.handles.peaksradup; - case 'down' - peakhandle=gui.handles.peaksraddown; - end - case 'globalcirc' - switch dir - case 'up' - peakhandle=gui.handles.globalpeakcircup; - case 'down' - peakhandle=gui.handles.globalpeakcircdown; - end - case 'globalrad' - switch dir - case 'up' - peakhandle=gui.handles.globalpeakradup; - case 'down' - peakhandle=gui.handles.globalpeakraddown; - end - end - - if ~strcmp(type,{'globalcirc','globalrad'}) - for i = gui.views2show - x(i)=get(peakhandle(i),'Xdata'); - y(i)=get(peakhandle(i),'Ydata'); - end - else - x=get(peakhandle,'Xdata'); - y=get(peakhandle,'Ydata'); - end - - [xclick,yclick]=mygetcurrentpoint(h); - [~,ind]=min((xclick-x).^2+(yclick-y).^2); - - switch type - case 'circ' - switch dir - case 'down' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''circ'',''down'',%d)',ind)); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''circ'',''down'',%d)',ind)); - case 'up' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''circ'',''up'',%d)',ind)); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''circ'',''up'',%d)',ind)); - end - case 'rad' - switch dir - case 'down' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''rad'',''down'',%d)',ind)); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''rad'',''down'',%d)',ind)); - case 'up' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''rad'',''up'',%d)',ind)); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''rad'',''up'',%d)',ind)); - end - case 'globalcirc' - switch dir - case 'down' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''globalcirc'',''down'')')); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''globalcirc'',''down'')')); - case 'up' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''globalcirc'',''up'')')); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''globalcirc'',''up'')')); - end - case 'globalrad' - switch dir - case 'down' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''globalrad'',''down'')')); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''globalrad'',''down'')')); - case 'up' - myset(gui.handles.fig,'windowbuttonmotionfcn',sprintf('straintagging.strainrate(''setpeakmotion'',''globalrad'',''up'')')); - myset(gui.handles.fig,'windowbuttonupfcn',sprintf('straintagging.strainrate(''setpeakbuttonup'',''globalrad'',''up'')')); - end - end - - -%------------------------------------------------------- -function setpeakmotion(type,dir,handleind)%type,ind) -%-------------------------------------------------- -global DATA -gui = DATA.GUI.strainrate ; -h=gui.handles.segaxes; - -switch type - case 'circ' - switch dir - case 'up' - peakhandle = gui.handles.peakscircup(handleind); - case 'down' - peakhandle = gui.handles.peakscircdown(handleind); - end - graphhandle=gui.handles.graphscirc(handleind); - - case 'rad' - switch dir - case 'up' - peakhandle = gui.handles.peaksradup(handleind); - case 'down' - peakhandle = gui.handles.peaksraddown(handleind); - end - graphhandle=gui.handles.graphsrad(handleind); - - case 'globalcirc' - switch dir - case 'up' - peakhandle = gui.handles.globalpeakcircup; - case 'down' - peakhandle = gui.handles.globalpeakcircdown; - end - graphhandle = gui.handles.globalgraphcirc; - case 'globalrad' - switch dir - case 'up' - peakhandle = gui.handles.globalpeakradup; - case 'down' - peakhandle = gui.handles.globalpeakraddown; - end - graphhandle = gui.handles.globalgraphrad; -end - -[xclicked,~]=mygetcurrentpoint(h); -x=get(graphhandle,'Xdata'); -[~,ind]=min((x-xclicked).^2); -y=get(graphhandle,'Ydata'); -set(peakhandle,'Xdata',x(ind),'Ydata',y(ind)) - -if get(gui.handles.typepopupmenu,'Value')>4 && ind>1 - ind=ind-1; -end - -switch type - case 'circ' - switch dir - case 'up' - gui.circupind(handleind) = ind; - gui.circup(handleind) = gui.srcirc(handleind,ind);%y(ind); - case 'down' - gui.circdownind(handleind) = ind; - gui.circdown(handleind) = gui.srcirc(handleind,ind);%y(ind); - end - case 'rad' - switch dir - case 'up' - gui.radupind(handleind) = ind; - gui.radup(handleind) = gui.srrad(handleind,ind);%y(ind); - case 'down' - gui.raddownind(handleind) = ind; - gui.raddown(handleind) = gui.srrad(handleind,ind);%y(ind); - end - case 'globalrad' - switch dir - case 'up' - gui.globalradupind = ind; - gui.globalradup = gui.globalsrrad(ind); - case 'down' - gui.globalraddownind = ind; - gui.globalraddown = gui.globalsrrad(ind); - end - case 'globalcirc' - switch dir - case 'up' - gui.globalcircupind = ind; - gui.globalcircup = gui.globalsrcirc(ind); - case 'down' - gui.globalcircdownind = ind; - gui.globalcircdown = gui.globalsrcirc(ind); - end -end - -for i=gui.views2show - set(gui.handles.(['text',num2str(i)]),'String',sprintf('%0.1f',gui.circup(i))) - set(gui.handles.(['text',num2str(17+i)]),'String',sprintf('%0.1f',gui.circdown(i))) - set(gui.handles.(['text',num2str(2*17+i)]),'String',sprintf('%0.1f',gui.radup(i))) - set(gui.handles.(['text',num2str(3*17+i)]),'String',sprintf('%0.1f',gui.raddown(i))) -end - - -set(gui.handles.('globalcircuptext'),'String',sprintf('%0.1f',gui.globalcircup)) -set(gui.handles.('globalcircdowntext'),'String',sprintf('%0.1f',gui.globalcircdown)) -set(gui.handles.('globalraduptext'),'String',sprintf('%0.1f',gui.globalradup)) -set(gui.handles.('globalraddowntext'),'String',sprintf('%0.1f',gui.globalraddown)) - - -function setpeakbuttonup(type,dir,handleind)%type,ind) -global DATA -gui = DATA.GUI.strainrate; - -if nargin<3 -setpeakmotion(type,dir) -else -setpeakmotion(type,dir,handleind) -end -set(gui.handles.fig,'windowbuttonmotionfcn',[]); -set(gui.handles.fig,'windowbuttonupfcn',[]) - -switch type - case 'circ' - myset(gui.handles.fig,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''circ'')')) - case 'rad' - myset(gui.handles.fig,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''rad'')')) - case '' -end - -function all_Callback -global DATA -gui = DATA.GUI.strainrate ; - -if gui.oneatatime - val=get(gui.handles.oneatatimecheckbox,'value'); - set(gui.handles.oneatatimecheckbox,'value',~val) - oneatatime_Callback; -end - - -for i=gui.radios2show - myset(gui.handles.(['radiobutton',num2str(i)]),'Value',1); -end - -radio_Callback - - -%----------------------------------------------- -function oneatatime_Callback -%--------------------------------------------- -global DATA -gui = DATA.GUI.strainrate; - -oneatatime=get(gui.handles.oneatatimecheckbox,'value'); -set(gui.handles.oneatatimecheckbox,'value',oneatatime); -gui.oneatatime=oneatatime; - -if oneatatime - ind=[]; - for i=1:17 - val=get(gui.handles.(['radiobutton',num2str(i)]),'Value'); - if val - ind=i; - break; - end - end - - if isempty(ind) - set(gui.handles.('radiobutton1'),'Value',1) - ind=1; - end - - for i=1:17 - myset(gui.handles.(['radiobutton',num2str(i)]),'Value',0); - end - myset(gui.handles.(['radiobutton',num2str(ind)]),'Value',1); - gui.lastpressed=ind; - - gui.views2show=ind; - -% %Auto detect global -% strlist=get(gui.handles.typepopupmenu,'String'); -% ind=get(gui.handles.typepopupmenu,'Value'); -% str=strlist{ind}; - -%if any(strcmp(str,{'Mean Longitudinal Strain Rate', 'Mean Radial Strain Rate', 'Mean Circumferential Strain Rate','Mean Longitudinal Strain with Tangents', 'Mean Radial Strain with Tangents', 'Mean Circumferential Strain with Tangents'})) - setglobalpeaks; -%end - - updateplot; -end -%---------------------------------------------------------------- -function radio_Callback -%--------------------------------------------------------------- -global DATA -gui = DATA.GUI.strainrate ; - -if gui.oneatatime - myset(gui.handles.(['radiobutton',num2str(gui.lastpressed)]),'Value',0); -end - -tmp=zeros(1,17); -for i=1:17 - tmp(i)=get(gui.handles.(['radiobutton',num2str(i)]),'Value'); -end - -if gui.oneatatime - lastpressed=find(tmp); - if isempty(lastpressed) - myset(gui.handles.(['radiobutton',num2str(gui.lastpressed)]),'Value',1); - return; - else - myset(gui.handles.(['radiobutton',num2str(lastpressed)]),'Value',1); - gui.lastpressed=lastpressed; - end -end - -gui.views2show=find(tmp); - -% %Auto detect global -% strlist=get(gui.handles.typepopupmenu,'String'); -% ind=get(gui.handles.typepopupmenu,'Value'); -% str=strlist{ind}; - -%if any(strcmp(str,{'Mean Longitudinal Strain Rate', 'Mean Radial Strain Rate', 'Mean Circumferential Strain Rate','Mean Longitudinal Strain with Tangents', 'Mean Radial Strain with Tangents', 'Mean Circumferential Strain with Tangents'})) - setglobalpeaks; -%end - -updateplot; - -%--------------------------------------- -function setglobalpeaks -%--------------------------------------- -global SET DATA -gui = DATA.GUI.strainrate; -%Auto detect global - -if strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - gui.globalsrrad = nanmean(gui.srrad(gui.views2show,:),1); - gui.globalsrcirc = nanmean(gui.srcirc(gui.views2show,:),1); -else - %global strainrate normalised if LAX images - normstrainratecirc=[]; - normstrainraterad =[]; - - for tagno = gui.taggroup - normstrainratecirc = [normstrainratecirc, conv2([1 0 -1],1,SET(tagno).StrainTagging.globalcirc,'valid')/(2/(SET(tagno).TSize-1))]; - normstrainraterad = [normstrainraterad, conv2([1 0 -1],1,SET(tagno).StrainTagging.globalrad,'valid')/(2/(SET(tagno).TSize-1))]; - end - - gui.globalsrcirc=nanmean(normstrainratecirc(:,gui.views2show),2); - gui.globalsrrad=nanmean(normstrainraterad(:,gui.views2show),2); -end - -%change value but not time -gui.globalradup=gui.globalsrrad(gui.globalradupind); -gui.globalraddown=gui.globalsrrad(gui.globalraddownind); -gui.globalcircup=gui.globalsrcirc(gui.globalcircupind); -gui.globalcircdown=gui.globalsrcirc(gui.globalcircdownind); - - -% [gui.globalradup, gui.globalradupind] = max(gui.globalsrrad); -% [gui.globalraddown, gui.globalraddownind] = min(gui.globalsrrad); -% [gui.globalcircup, gui.globalcircupind] = max(gui.globalsrcirc); -% [gui.globalcircdown, gui.globalcircdownind] = min(gui.globalsrcirc); - - -%---------------------------------------- -function plotNonSegmentedStrainrate(h,tvec,straincurve,type,normalizedtime) -%---------------------------------------- -global DATA - -if nargin<5 - normalizedtime=0; -end -gui=DATA.GUI.strainrate; - -switch type - case 'globalcirc' - downslope=gui.globalcircdown; - inddown=gui.globalcircdownind; - upslope=gui.globalcircup; - indup=gui.globalcircupind; - case 'globalrad' - downslope=gui.globalraddown; - inddown=gui.globalraddownind; - upslope=gui.globalradup; - indup=gui.globalradupind; -end - -plot(h,tvec,straincurve,'.-','linewidth',2,'Color','b') -hold(h,'on') -inddown = inddown+1; -indup=indup+1; -downtime = tvec(inddown); -uptime = tvec(indup); -plot(h,downtime,straincurve(inddown),'r+','markersize',10,'linewidth',3) -plot(h,uptime,straincurve(indup),'k+','markersize',10,'linewidth',3) - -tangentplot(h,tvec,straincurve,normalizedtime,inddown,indup,downtime,uptime); - -% xlim(h,[tvec(1),tvec(end)]) -% ylim(h,'manual') -% xlim(h,'manual') -% x=-SET(gui.taggroup(1)).TSize:SET(gui.taggroup(1)).TSize; -% if ~normalizedtime -% uptan_t=uptime+x*SET(gui.taggroup(1)).TIncr; -% downtan_t=downtime+x*SET(gui.taggroup(1)).TIncr; -% -% uptan = upslope*SET(gui.taggroup(1)).TIncr*x+straincurve(indup); -% downtan = downslope*SET(gui.taggroup(1)).TIncr*x+straincurve(inddown); -% else -% uptan_t=uptime+x/(SET(gui.taggroup(1)).TSize-1); -% downtan_t=downtime+x/(SET(gui.taggroup(1)).TSize-1); -% -% uptan = upslope/(SET(gui.taggroup(1)).TSize-1)*x+straincurve(indup); -% downtan = downslope/(SET(gui.taggroup(1)).TSize-1)*x+straincurve(inddown); -% end -% -% gui.handles.tup = plot(h,uptan_t,uptan,'k--'); -% gui.handles.tdown = plot(h,downtan_t,downtan,'k--'); - -% if ~normalizedtime -% m=straincurve(indup+1)-upslope*SET(gui.taggroup(1)).TIncr*indup; -% else -% m=straincurve(indup+1)-upslope/(SET(gui.taggroup(1)).TSize-1)*indup; -% end -% -% xup(1)=(yl(1)-m)/upslope; -% xup(2)=(yl(2)-m)/upslope; -% -% if ~normalizedtime -% m=straincurve(inddown+1)-downslope*SET(gui.taggroup(1)).TIncr*inddown; -% else -% m=straincurve(inddown+1)-downslope/(SET(gui.taggroup(1)).TSize-1)*inddown; -% end -% -% xdown(1)=(yl(1)-m)/downslope; -% % xdown(2)=(yl(2)-m)/downslope; -% gui.handles.tup = plot(h,xup,yl,'k--'); -% gui.handles.tdown = plot(h,xdown,yl,'k--'); -function tangentplot(h,tvec,straincurve,normalizedtime,inddown,indup,downtime,uptime,downslope,upslope) -global SET DATA - -gui=DATA.GUI.strainrate; - - -if ~strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - if indup~=1 - upslope = -(straincurve(indup-1)-straincurve(indup+1))/(2/(SET(gui.taggroup(1)).TSize-1)); - else - upslope = -(straincurve(indup)-straincurve(indup+1))/(1/(SET(gui.taggroup(1)).TSize-1)); - end - if inddown~=1 - downslope = -(straincurve(inddown-1)-straincurve(inddown+1))/(2/(SET(gui.taggroup(1)).TSize-1)); - else - downslope = -(straincurve(inddown)-straincurve(inddown+1))/(1/(SET(gui.taggroup(1)).TSize-1)); - end -else - if indup~=1 - upslope = -(straincurve(indup-1)-straincurve(indup+1))/(2*SET(gui.taggroup(1)).TIncr); - else - upslope = -(straincurve(indup)-straincurve(indup+1))/(1*SET(gui.taggroup(1)).TIncr); - end - if inddown~=1 - downslope = -(straincurve(inddown-1)-straincurve(inddown+1))/(2*SET(gui.taggroup(1)).TIncr); - else - downslope = -(straincurve(inddown)-straincurve(inddown+1))/(1*SET(gui.taggroup(1)).TIncr); - end -end - -xlim(h,[tvec(1),tvec(end)]) -ylim(h,'manual') -xlim(h,'manual') -x=-SET(gui.taggroup(1)).TSize:SET(gui.taggroup(1)).TSize; -if ~normalizedtime - uptan_t=uptime+x*SET(gui.taggroup(1)).TIncr; - downtan_t=downtime+x*SET(gui.taggroup(1)).TIncr; - - uptan = upslope*SET(gui.taggroup(1)).TIncr*x+straincurve(indup); - downtan = downslope*SET(gui.taggroup(1)).TIncr*x+straincurve(inddown); -else - uptan_t=uptime+x/(SET(gui.taggroup(1)).TSize-1); - downtan_t=downtime+x/(SET(gui.taggroup(1)).TSize-1); - - uptan = upslope/(SET(gui.taggroup(1)).TSize-1)*x+straincurve(indup); - downtan = downslope/(SET(gui.taggroup(1)).TSize-1)*x+straincurve(inddown); -end - -gui.handles.tup = plot(h,uptan_t,uptan,'k--'); -gui.handles.tdown = plot(h,downtan_t,downtan,'k--'); - -function updateplot -global DATA SET - -gui = DATA.GUI.strainrate ; -myset(gui.handles.fig,'ButtonDownFcn',[]) -h=gui.handles.segaxes; -legend(h,'off') - -cla(h) -%cla(gui.handles.reportaxes) -%changed curve choice need to redo globalpeaks -% if gui.popupind~=get(gui.handles.typepopupmenu,'Value'); -% setglobalpeaks; -% gui.popupind=get(gui.handles.typepopupmenu,'Value'); -% end - -set(h,'yticklabelmode','auto') -set(h,'ytickmode','auto') - -ylim(h,'auto') -xlim(h,'auto') -% get names of segments - -strlist=get(gui.handles.typepopupmenu,'String'); -ind=get(gui.handles.typepopupmenu,'Value'); -str=strlist{ind}; - -hold(h,'on') -grid(h,'on'); - -used=find(gui.include); - -if ~strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - normalizedtime=1; - tvec=linspace(0,1,SET(gui.taggroup(1)).TSize); - srtvec=tvec(2:end-1); -else - srtvec=gui.tvec; - tvec=SET(gui.taggroup(1)).TimeVector; - normalizedtime=0; -end - - -switch str - case 'Mean Longitudinal Strain with Tangents' - straincurves=[]; - counter=1; - - for tagno=gui.taggroup - straincurves = [straincurves, SET(tagno).StrainTagging.globalcirc]; - end - - straincurve=mynanmean(straincurves(:,gui.views2show),2); - plotNonSegmentedStrainrate(h,tvec,straincurve,'globalcirc',normalizedtime); - - case 'Mean Circumferential Strain with Tangents' - straincurve=mynanmean(SET(gui.taggroup(1)).StrainTagging.globalcirc(:,used(gui.views2show)),2); - plotNonSegmentedStrainrate(h,SET(gui.taggroup(1)).TimeVector,straincurve,'globalcirc'); - - case 'Mean Radial Strain with Tangents' - straincurves=[]; - - for tagno=gui.taggroup - straincurves = [straincurves, SET(tagno).StrainTagging.globalrad]; - end - if strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - straincurve=mynanmean(straincurves(:,used(gui.views2show)),2); - else - straincurve=mynanmean(straincurves(:,gui.views2show),2); - end - plotNonSegmentedStrainrate(h,tvec,straincurve,'globalrad',normalizedtime); - - case {'Longitudinal Strain with Tangents','Circumferential Strain with Tangents'} - straincurve = nan(SET(gui.taggroup(1)).TSize,length(gui.taggroup)); - used = find(gui.include); - for i=gui.views2show - if strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - straincurve(:,i)=SET(gui.taggroup(1)).StrainTagging.globalcirc(:,used(i)); - else - straincurve(:,i)=SET(gui.taggroup(i)).StrainTagging.globalcirc; -% switch SET(gui.taggroup(used(i))).ImageViewPlane -% case '2CH' -% straincurve(:,1)=SET(gui.taggroup(used(i))).StrainTagging.globalcirc; -% case '3CH' -% straincurve(:,end-1)=SET(gui.taggroup(i)).StrainTagging.globalcirc; -% case '4CH' -% straincurve(:,end)=SET(gui.taggroup(i)).StrainTagging.globalcirc; -% end - end - end - for i = gui.views2show - gui.handles.graphscirc(i)=plot(h,tvec,straincurve(:,i),'.-','linewidth',2,'Color',gui.cmap(i,:)); - gui.handles.peakscircup(i)=plot(h,srtvec(gui.circupind(i)), straincurve(gui.circupind(i)+1,i),'k+','markersize',10,'linewidth',3); - gui.handles.peakscircdown(i)=plot(h,srtvec(gui.circdownind(i)), straincurve(gui.circdownind(i)+1,i),'r+','markersize',10,'linewidth',3); - myset(gui.handles.peakscircup(i),'ButtonDownFcn',''); - myset(gui.handles.peakscircdown(i),'ButtonDownFcn',''); - myset(gui.handles.graphscirc(i),'ButtonDownFcn',''); - end - - - for i = gui.views2show - tangentplot(h,tvec,straincurve(:,i),normalizedtime,gui.circdownind(i)+1,gui.circupind(i)+1,... - srtvec(gui.circdownind(i)),srtvec(gui.circupind(i)),gui.circdown(i),gui.circup(i)); - end - - myset(h,'ButtonDownFcn',''); - - case'Radial Strain with Tangents' - straincurve = nan(SET(gui.taggroup(1)).TSize,length(gui.views2show)); - used = find(gui.include); - for i=1:length(used) - if strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - straincurve(:,i)=SET(gui.taggroup(1)).StrainTagging.globalrad(:,used(i)); - else - straincurve(:,i)=SET(gui.taggroup(i)).StrainTagging.globalrad; -% switch SET(gui.taggroup(i)).ImageViewPlane -% case '2CH' -% straincurve(:,1)=SET(gui.taggroup(i)).StrainTagging.globalrad; -% case '3CH' -% straincurve(:,end-1)=SET(gui.taggroup(i)).StrainTagging.globalrad; -% case '4CH' -% straincurve(:,end)=SET(gui.taggroup(i)).StrainTagging.globalrad; -% end - end - end - for i = gui.views2show - gui.handles.graphsrad(i)=plot(h,tvec,straincurve(:,i),'.-','linewidth',2,'Color',gui.cmap(i,:)); - gui.handles.peaksradup(i)=plot(h,srtvec(gui.radupind(i)), straincurve(gui.radupind(i)+1,i),'k+','markersize',10,'linewidth',3); - gui.handles.peaksraddown(i)=plot(h,srtvec(gui.raddownind(i)), straincurve(gui.raddownind(i)+1,i),'r+','markersize',10,'linewidth',3); - - myset(gui.handles.peakscircup(i),'ButtonDownFcn',''); - myset(gui.handles.peakscircdown(i),'ButtonDownFcn',''); - myset(gui.handles.graphscirc(i),'ButtonDownFcn',''); - end - - for i = gui.views2show - tangentplot(h,tvec,straincurve(:,i),normalizedtime,gui.raddownind(i)+1,gui.radupind(i)+1,... - srtvec(gui.raddownind(i)),srtvec(gui.radupind(i)),gui.raddown(i),gui.radup(i)); - end - myset(h,'ButtonDownFcn',''); - - - case {'Circumferential Strain Rate', 'Longitudinal Strain Rate'} - for i = gui.views2show - gui.handles.graphscirc(i)=plot(h,srtvec,gui.srcirc(i,:),'.-','linewidth',2,'Color',gui.cmap(i,:)); - gui.handles.peakscircup(i)=plot(h,srtvec(gui.circupind(i)), gui.circup(i),'k+','markersize',10,'linewidth',3); - gui.handles.peakscircdown(i)=plot(h,srtvec(gui.circdownind(i)), gui.circdown(i),'r+','markersize',10,'linewidth',3); - myset(gui.handles.peakscircup(i),'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''circ'',''up'')')); - myset(gui.handles.peakscircdown(i),'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''circ'',''down'')')); - myset(gui.handles.graphscirc(i),'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''circ'')')); - end - yl=ylim; - xl=[srtvec(1),srtvec(end)]; - set(h,'XLim',xl,'YLim',yl) - myset(h,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''circ'')')); - - - case 'Radial Strain Rate' - for i = gui.views2show - gui.handles.graphsrad(i)=plot(h,srtvec,gui.srrad(i,:),'.-','linewidth',2,'Color',gui.cmap(i,:)); - gui.handles.peaksradup(i)=plot(h,srtvec(gui.radupind(i)), gui.radup(i),'k+','markersize',10,'linewidth',3); - gui.handles.peaksraddown(i)=plot(h,srtvec(gui.raddownind(i)), gui.raddown(i),'r+','markersize',10,'linewidth',3); - myset(gui.handles.peaksradup(i),'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''rad'',''up'')')); - myset(gui.handles.peaksraddown(i),'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''rad'',''down'')')); - myset(gui.handles.graphsrad(i),'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''rad'')')); - end - yl=ylim; - xl=[srtvec(1),srtvec(end)]; - set(h,'XLim',xl,'YLim',yl) - myset(h,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''rad'')')); - - case {'Mean Circumferential Strain Rate', 'Mean Longitudinal Strain Rate'} - gui.handles.globalgraphcirc=plot(h,srtvec,gui.globalsrcirc,'.-','linewidth',2,'Color','b'); - gui.handles.globalpeakcircup=plot(h,srtvec(gui.globalcircupind), gui.globalcircup,'k+','markersize',10,'linewidth',3); - gui.handles.globalpeakcircdown=plot(h,srtvec(gui.globalcircdownind), gui.globalcircdown,'r+','markersize',10,'linewidth',3); - - myset(gui.handles.globalpeakcircup,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalcirc'',''up'')')); - myset(gui.handles.globalpeakcircdown,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalcirc'',''down'')')); - myset(gui.handles.globalgraphcirc,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalcirc'')')); - - yl=ylim; - xl=[srtvec(1),srtvec(end)]; - set(h,'XLim',xl,'YLim',yl) - myset(h,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalcirc'')')); - - - case 'Mean Radial Strain Rate' - gui.handles.globalgraphrad=plot(h,srtvec,gui.globalsrrad,'.-','linewidth',2,'Color','b'); - gui.handles.globalpeakradup=plot(h,srtvec(gui.globalradupind), gui.globalradup,'k+','markersize',10,'linewidth',3); - gui.handles.globalpeakraddown=plot(h,srtvec(gui.globalraddownind), gui.globalraddown,'r+','markersize',10,'linewidth',3); - - myset(gui.handles.globalpeakradup,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalrad'',''up'')')); - myset(gui.handles.globalpeakraddown,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalrad'',''down'')')); - myset(gui.handles.globalgraphrad,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalrad'')')); - - yl=ylim; - xl=[srtvec(1),srtvec(end)]; - set(h,'XLim',xl,'YLim',yl) - myset(h,'ButtonDownFcn',sprintf('straintagging.strainrate(''setpeak_Callback'',''globalrad'')')); - -end - -if strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis')%~any(strcmp(str,{'Mean Longitudinal Strain with Tangents','Mean Radial Strain with Tangents','Mean Longitudinal Strain Rate','Mean Radial Strain Rate','Mean Longitudinal Strain Rate','Radial Strain Rate'})) || strcmp(SET(gui.taggroup(1)).ImageViewPlane,'Short-axis') - xlabel(h,'Time [s]') -else - xlabel(h,'Heart cycle [s/T]') -end - -if ind >4 - ylabel(h,'%/s') -else - ylabel(h,'%') -end -hold(h,'off') - -for i=gui.views2show - set(gui.handles.(['text',num2str(i)]),'String',sprintf('%0.1f',gui.circup(i))) - set(gui.handles.(['text',num2str(17+i)]),'String',sprintf('%0.1f',gui.circdown(i))) - set(gui.handles.(['text',num2str(2*17+i)]),'String',sprintf('%0.1f',gui.radup(i))) - set(gui.handles.(['text',num2str(3*17+i)]),'String',sprintf('%0.1f',gui.raddown(i))) -end - -set(gui.handles.('globalcircuptext'),'String',sprintf('%0.1f',gui.globalcircup)) -set(gui.handles.('globalcircdowntext'),'String',sprintf('%0.1f',gui.globalcircdown)) -set(gui.handles.('globalraduptext'),'String',sprintf('%0.1f',gui.globalradup)) -set(gui.handles.('globalraddowntext'),'String',sprintf('%0.1f',gui.globalraddown)) - -function export_Callback -global DATA SET -gui = DATA.GUI.strainrate ; - -col=1; -line=1; -outdata{line,1} = 'Patient Name'; -outdata{line,2} = 'Patient ID'; -outdata{line,3} = 'Heart Rate'; -outdata{line,4} = 'Image Type'; - -line=2; -outdata{line,1} = SET(no).PatientInfo.Name; -outdata{line,2} = SET(no).PatientInfo.ID; -outdata{line,3} = SET(no).HeartRate; -outdata{line,4} = sprintf('%s %s',SET(no).ImageType,SET(no).ImageViewPlane); -% -% %Write relevant gui parameters to outdatacell -% out{line,5} = gui.radup; -% sr.radupind = gui.radupind; -% sr.raddown = gui.raddown; -% sr.raddownind = gui.raddownind; -% sr.circup = gui.circup; -% sr.circupind=gui.circupind; -% sr.circdown=gui.circdown; -% sr.circdownind=gui.circdownind; -% sr.srcirc = gui.srcirc; -% sr.srrad = gui.srrad; -% sr.include = gui.include; -% sr.globalcircup=gui.globalcircup; -% sr.globalcircdown=gui.globalcircdown; -% sr.globalcircupind=gui.globalcircupind; -% sr.globalcircdownind=gui.globalcircdownind; -% sr.globalradup=gui.globalradup; -% sr.globalraddown=gui.globalraddown; -% sr.globalradupind=gui.globalradupind; -% sr.globalraddownind=gui.globalraddownind; -% sr.globalsrcirc=gui.globalsrcirc; -% sr.globalsrrad=gui.globalsrrad; - -function save_Callback -global DATA SET -gui = DATA.GUI.strainrate ; - -%Write relevant gui parameters to SET structure -sr.radup = gui.radup; -sr.radupind = gui.radupind; -sr.raddown = gui.raddown; -sr.raddownind = gui.raddownind; -sr.circup = gui.circup; -sr.circupind=gui.circupind; -sr.circdown=gui.circdown; -sr.circdownind=gui.circdownind; -sr.srcirc = gui.srcirc; -sr.srrad = gui.srrad; -sr.include = gui.include; -sr.globalcircup=gui.globalcircup; -sr.globalcircdown=gui.globalcircdown; -sr.globalcircupind=gui.globalcircupind; -sr.globalcircdownind=gui.globalcircdownind; -sr.globalradup=gui.globalradup; -sr.globalraddown=gui.globalraddown; -sr.globalradupind=gui.globalradupind; -sr.globalraddownind=gui.globalraddownind; -sr.globalsrcirc=gui.globalsrcirc; -sr.globalsrrad=gui.globalsrrad; - -for no = gui.taggroup - SET(no).StrainTagging.SR=sr; -end - -close_Callback - -function close_Callback -global DATA - -try - DATA.GUI.strainrate = close(DATA.GUI.strainrate ); -catch %#ok - DATA.GUI.strainrate =[]; - delete(gcbf); -end diff --git a/source/+straintagging/strainrate.p b/source/+straintagging/strainrate.p new file mode 100644 index 0000000..4984806 Binary files /dev/null and b/source/+straintagging/strainrate.p differ diff --git a/source/+straintagging/strainselectslices.fig b/source/+straintagging/strainselectslices.fig index e653c6b..ce5eb51 100644 Binary files a/source/+straintagging/strainselectslices.fig and b/source/+straintagging/strainselectslices.fig differ diff --git a/source/+straintagging/strainselectslices.p b/source/+straintagging/strainselectslices.p index a7f42cf..3b20e65 100644 Binary files a/source/+straintagging/strainselectslices.p and b/source/+straintagging/strainselectslices.p differ diff --git a/source/+straintagging/straintagging.p b/source/+straintagging/straintagging.p index e176b3b..d5b7ea3 100644 Binary files a/source/+straintagging/straintagging.p and b/source/+straintagging/straintagging.p differ diff --git a/source/+straintagging/straintools.p b/source/+straintagging/straintools.p new file mode 100644 index 0000000..d4f80d0 Binary files /dev/null and b/source/+straintagging/straintools.p differ diff --git a/source/+t2star/t2star.fig b/source/+t2star/t2star.fig index 4847b35..9e490f4 100644 Binary files a/source/+t2star/t2star.fig and b/source/+t2star/t2star.fig differ diff --git a/source/+t2star/t2star.p b/source/+t2star/t2star.p index bbcf15a..99f6a00 100644 Binary files a/source/+t2star/t2star.p and b/source/+t2star/t2star.p differ diff --git a/source/+t2star/t2star_ADAPTS6.p b/source/+t2star/t2star_ADAPTS6.p index 5c8b599..711fe46 100644 Binary files a/source/+t2star/t2star_ADAPTS6.p and b/source/+t2star/t2star_ADAPTS6.p differ diff --git a/source/+transfer/addcomment.m b/source/+transfer/addcomment.m deleted file mode 100644 index 07ea628..0000000 --- a/source/+transfer/addcomment.m +++ /dev/null @@ -1,39 +0,0 @@ -function addcomment -%Add a comment to current image stack - -%Nils Lundahl -global DATA SET NO - -if ~DATA.DataLoaded - myfailed('No data loaded.'); - return; -end; - -comment = struct('Username','Unknown','Time','','Text',''); - -%Extract environemnt variable containing username of windows machines -if ispc - comment.Username = getenv('USERNAME'); -else - comment.Username = 'Unkown'; %Added Einar -end - -txt = inputdlg(comment.Username,'Enter comment',[10 80]); - -%Add it -if ~isempty(txt) - stri = ''; - for li = 1:size(txt{1},1) - stri = [stri strtrim(txt{1}(li,:)) '\n']; - end - comment.Text = sprintf(stri); - comment.Time = datestr(now,31); - if isfield(SET,'Comment') && ~isempty(SET(NO).Comment) - SET(NO).Comment = [SET(NO).Comment comment]; - else - SET(NO).Comment = comment; - end -else - myfailed('Empty comment. Ignored.'); -end - diff --git a/source/+transfer/addcomment.p b/source/+transfer/addcomment.p new file mode 100644 index 0000000..8b44736 Binary files /dev/null and b/source/+transfer/addcomment.p differ diff --git a/source/+transfer/base64decode.m b/source/+transfer/base64decode.m deleted file mode 100644 index 447cfca..0000000 --- a/source/+transfer/base64decode.m +++ /dev/null @@ -1,103 +0,0 @@ -function y = base64decode(x) -%BASE64DECODE Perform base64 decoding on a string. -% -% BASE64DECODE(STR) decodes the given base64 string STR. -% -% Any character not part of the 65-character base64 subset set is silently -% ignored. Characters occuring after a '=' padding character are never -% decoded. -% -% STR doesn't have to be a string. The only requirement is that it is a -% vector containing values in the range 0-255. -% -% If the length of the string to decode (after ignoring non-base64 chars) is -% not a multiple of 4, then a warning is generated. -% -% This function is used to decode strings from the Base64 encoding specified -% in RFC 2045 - MIME (Multipurpose Internet Mail Extensions). The Base64 -% encoding is designed to represent arbitrary sequences of octets in a form -% that need not be humanly readable. A 65-character subset ([A-Za-z0-9+/=]) -% of US-ASCII is used, enabling 6 bits to be represented per printable -% character. -% -% See also BASE64ENCODE. - -% Author: Peter John Acklam -% Time-stamp: 2004-09-20 08:20:50 +0200 -% E-mail: pjacklam@online.no -% URL: http://home.online.no/~pjacklam - - % check number of input arguments - error(nargchk(1, 1, nargin)); - - % remove non-base64 chars - x = x ( ( 'A' <= x & x <= 'Z' ) ... - | ( 'a' <= x & x <= 'z' ) ... - | ( '0' <= x & x <= '9' ) ... - | ( x == '+' ) | ( x == '=' ) | ( x == '/' ) ); - - if rem(length(x), 4) - warning('Length of base64 data not a multiple of 4; padding input.'); - end - - k = find(x == '='); - if ~isempty(k) - x = x(1:k(1)-1); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Now perform the following mapping - % - % A-Z -> 0 - 25 - % a-z -> 26 - 51 - % 0-9 -> 52 - 61 - % + -> 62 - % / -> 63 - - y = repmat(uint8(0), size(x)); - i = 'A' <= x & x <= 'Z'; y(i) = - 'A' + x(i); - i = 'a' <= x & x <= 'z'; y(i) = 26 - 'a' + x(i); - i = '0' <= x & x <= '9'; y(i) = 52 - '0' + x(i); - i = x == '+'; y(i) = 62 - '+' + x(i); - i = x == '/'; y(i) = 63 - '/' + x(i); - x = y; - - nebytes = length(x); % number of encoded bytes - nchunks = ceil(nebytes/4); % number of chunks/groups - - % add padding if necessary - if rem(nebytes, 4) - x(end+1 : 4*nchunks) = 0; - end - - x = reshape(uint8(x), 4, nchunks); - y = repmat(uint8(0), 3, nchunks); % for the decoded data - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Rearrange every 4 bytes into 3 bytes - % - % 00aaaaaa 00bbbbbb 00cccccc 00dddddd - % - % to form - % - % aaaaaabb bbbbcccc ccdddddd - - y(1,:) = bitshift(x(1,:), 2); % 6 highest bits of y(1,:) - y(1,:) = bitor(y(1,:), bitshift(x(2,:), -4)); % 2 lowest bits of y(1,:) - - y(2,:) = bitshift(x(2,:), 4); % 4 highest bits of y(2,:) - y(2,:) = bitor(y(2,:), bitshift(x(3,:), -2)); % 4 lowest bits of y(2,:) - - y(3,:) = bitshift(x(3,:), 6); % 2 highest bits of y(3,:) - y(3,:) = bitor(y(3,:), x(4,:)); % 6 lowest bits of y(3,:) - - % remove padding - switch rem(nebytes, 4) - case 2 - y = y(1:end-2); - case 3 - y = y(1:end-1); - end - - % reshape to a row vector and make it a character array - y = char(reshape(y, 1, numel(y))); diff --git a/source/+transfer/base64encode.m b/source/+transfer/base64encode.m deleted file mode 100644 index 92b41d2..0000000 --- a/source/+transfer/base64encode.m +++ /dev/null @@ -1,159 +0,0 @@ -function y = base64encode(x, eol) -%BASE64ENCODE Perform base64 encoding on a string. -% -% BASE64ENCODE(STR, EOL) encode the given string STR. EOL is the line ending -% sequence to use; it is optional and defaults to '\n' (ASCII decimal 10). -% The returned encoded string is broken into lines of no more than 76 -% characters each, and each line will end with EOL unless it is empty. Let -% EOL be empty if you do not want the encoded string broken into lines. -% -% STR and EOL don't have to be strings (i.e., char arrays). The only -% requirement is that they are vectors containing values in the range 0-255. -% -% This function may be used to encode strings into the Base64 encoding -% specified in RFC 2045 - MIME (Multipurpose Internet Mail Extensions). The -% Base64 encoding is designed to represent arbitrary sequences of octets in a -% form that need not be humanly readable. A 65-character subset -% ([A-Za-z0-9+/=]) of US-ASCII is used, enabling 6 bits to be represented per -% printable character. -% -% Examples -% -------- -% -% If you want to encode a large file, you should encode it in chunks that are -% a multiple of 57 bytes. This ensures that the base64 lines line up and -% that you do not end up with padding in the middle. 57 bytes of data fills -% one complete base64 line (76 == 57*4/3): -% -% If ifid and ofid are two file identifiers opened for reading and writing, -% respectively, then you can base64 encode the data with -% -% while ~feof(ifid) -% fwrite(ofid, base64encode(fread(ifid, 60*57))); -% end -% -% or, if you have enough memory, -% -% fwrite(ofid, base64encode(fread(ifid))); -% -% See also BASE64DECODE. - -% Author: Peter John Acklam -% Time-stamp: 2004-02-03 21:36:56 +0100 -% E-mail: pjacklam@online.no -% URL: http://home.online.no/~pjacklam - - % check number of input arguments - error(nargchk(1, 2, nargin)); - - % make sure we have the EOL value - if nargin < 2 - eol = sprintf('\n'); - else - if sum(size(eol) > 1) > 1 - error('EOL must be a vector.'); - end - if any(eol(:) > 255) - error('EOL can not contain values larger than 255.'); - end - end - - if sum(size(x) > 1) > 1 - error('STR must be a vector.'); - end - - x = uint8(x); - eol = uint8(eol); - - ndbytes = length(x); % number of decoded bytes - nchunks = ceil(ndbytes / 3); % number of chunks/groups - nebytes = 4 * nchunks; % number of encoded bytes - - % add padding if necessary, to make the length of x a multiple of 3 - if rem(ndbytes, 3) - x(end+1 : 3*nchunks) = 0; - end - - x = reshape(x, [3, nchunks]); % reshape the data - y = repmat(uint8(0), 4, nchunks); % for the encoded data - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Split up every 3 bytes into 4 pieces - % - % aaaaaabb bbbbcccc ccdddddd - % - % to form - % - % 00aaaaaa 00bbbbbb 00cccccc 00dddddd - % - y(1,:) = bitshift(x(1,:), -2); % 6 highest bits of x(1,:) - - y(2,:) = bitshift(bitand(x(1,:), 3), 4); % 2 lowest bits of x(1,:) - y(2,:) = bitor(y(2,:), bitshift(x(2,:), -4)); % 4 highest bits of x(2,:) - - y(3,:) = bitshift(bitand(x(2,:), 15), 2); % 4 lowest bits of x(2,:) - y(3,:) = bitor(y(3,:), bitshift(x(3,:), -6)); % 2 highest bits of x(3,:) - - y(4,:) = bitand(x(3,:), 63); % 6 lowest bits of x(3,:) - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Now perform the following mapping - % - % 0 - 25 -> A-Z - % 26 - 51 -> a-z - % 52 - 61 -> 0-9 - % 62 -> + - % 63 -> / - % - % We could use a mapping vector like - % - % ['A':'Z', 'a':'z', '0':'9', '+/'] - % - % but that would require an index vector of class double. - % - z = repmat(uint8(0), size(y)); - i = y <= 25; z(i) = 'A' + double(y(i)); - i = 26 <= y & y <= 51; z(i) = 'a' - 26 + double(y(i)); - i = 52 <= y & y <= 61; z(i) = '0' - 52 + double(y(i)); - i = y == 62; z(i) = '+'; - i = y == 63; z(i) = '/'; - y = z; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Add padding if necessary. - % - npbytes = 3 * nchunks - ndbytes; % number of padding bytes - if npbytes - y(end-npbytes+1 : end) = '='; % '=' is used for padding - end - - if isempty(eol) - - % reshape to a row vector - y = reshape(y, [1, nebytes]); - - else - - nlines = ceil(nebytes / 76); % number of lines - neolbytes = length(eol); % number of bytes in eol string - - % pad data so it becomes a multiple of 76 elements - y(nebytes + 1 : 76 * nlines) = 0; - y = reshape(y, 76, nlines); - - % insert eol strings - eol = eol(:); - y(end + 1 : end + neolbytes, :) = eol(:, ones(1, nlines)); - - % remove padding, but keep the last eol string - m = nebytes + neolbytes * (nlines - 1); - n = (76+neolbytes)*nlines - neolbytes; - y(m+1 : n) = ''; - - % extract and reshape to row vector - y = reshape(y, 1, m+neolbytes); - - end - - % output is a character array - y = char(y); diff --git a/source/+transfer/base64encode.p b/source/+transfer/base64encode.p new file mode 100644 index 0000000..c4b8f33 Binary files /dev/null and b/source/+transfer/base64encode.p differ diff --git a/source/+transfer/checkpattern.m b/source/+transfer/checkpattern.m deleted file mode 100644 index b57f742..0000000 --- a/source/+transfer/checkpattern.m +++ /dev/null @@ -1,90 +0,0 @@ -function [ok,msg] = checkpattern(pattern,newname) -%Check if the new name is valid according to the pattern. - -ok = true; -msg = ''; - -if isequal(newname,pattern) - ok = false; - msg = 'You need to change the default value. Upload aborted.'; - return; -end; - -if ~isequal(length(newname),length(pattern)) - ok = false; - msg = sprintf('Length of new name and pattern need to be same. Length of pattern is %d and length of new name is %d',... - length(pattern),length(newname)); - return; -end; - -for loop = 1:length(pattern) - - %If it is a dash then it should be a dash - if isequal(pattern(loop),'-') && ~isequal(newname(loop),'-') - ok = false; - msg = sprintf('Need to have a dash in position %d.',loop); - return; - end; - - %If it is a colon then it should be a dash - if isequal(pattern(loop),':') && ~isequal(newname(loop),':') - ok = false; - msg = sprintf('Need to have a colon in position %d.',loop); - return; - end; - - %If it is a semi-colon then it should be a - if isequal(pattern(loop),';') && ~isequal(newname(loop),';') - ok = false; - msg = sprintf('Need to have a semi-colon in position %d.',loop); - return; - end; - - %If it is a point then it should be a - if isequal(pattern(loop),'.') && ~isequal(newname(loop),'.') - ok = false; - msg = sprintf('Need to have a point in position %d.',loop); - return; - end; - - %If it is a space then it should be a - if isequal(pattern(loop),' ') && ~isequal(newname(loop),' ') - ok = false; - msg = sprintf('Need to have a space in position %d.',loop); - return; - end; - - %If it is an underscore then it should be a - if isequal(pattern(loop),'_') && ~isequal(newname(loop),'_') - ok = false; - msg = sprintf('Need to have an underscorein position %d.',loop); - return; - end; - - %It is a upper case letter => should be equal - if isequal(pattern(loop),upper(pattern(loop))) - if ~isequal(pattern(loop),newname(loop)) - ok = false; - msg = sprintf('Letter number %d needs to be a ''%s''',loop,pattern(loop)); - end; - end; - - %If it is a lower case n then it should be numeric - if isequal(pattern(loop),'n') %#ok - if ~ismember(newname(loop),'0123456789') - ok = false; - msg = sprintf('New name in position %d needs to be numeric.',loop); - return; - end; - end; - - %If it is a lower case x then it should be non numeric - if isequal(pattern(loop),'x') %#ok - if ismember(newname(loop),'0123456789') - ok = false; - msg = sprintf('New name in position %d needs to be non-numeric.',loop); - return; - end; - end; - -end; \ No newline at end of file diff --git a/source/+transfer/createcredentials.fig b/source/+transfer/createcredentials.fig new file mode 100644 index 0000000..3c6b3da Binary files /dev/null and b/source/+transfer/createcredentials.fig differ diff --git a/source/+transfer/createcredentials.p b/source/+transfer/createcredentials.p new file mode 100644 index 0000000..4d91be9 Binary files /dev/null and b/source/+transfer/createcredentials.p differ diff --git a/source/+transfer/deltree.m b/source/+transfer/deltree.m deleted file mode 100644 index 3ebe6d9..0000000 --- a/source/+transfer/deltree.m +++ /dev/null @@ -1,14 +0,0 @@ -function deltree(fileLocation) -% Works like deltree /y in good old Windows. -% You can specify files, folders, or wildcards. -% -% Example: deltree('C:\Temp\Administrator\*.*'); - -if( ispc ) - executeString = sprintf('del /s /q %s', fileLocation); - system(executeString); - rmdir(fileLocation, 's'); -else - executeString = sprintf('rm -Rf %s', fileLocation); - system(executeString); -end diff --git a/source/+transfer/exception2str.m b/source/+transfer/exception2str.m deleted file mode 100644 index 1d14271..0000000 --- a/source/+transfer/exception2str.m +++ /dev/null @@ -1,9 +0,0 @@ -function str = exception2str(e) - str = ''; - str = [str sprintf('Error message:\n%s\n\n',e.message) ]; - str = [str sprintf('Stack trace:\n') ]; - for i=1:numel(e.stack) - str = [str sprintf('Line %d in ''%s''\n', e.stack(i).line, e.stack(i).file) ]; - end - str = [str sprintf('\nEnd\n') ]; -end \ No newline at end of file diff --git a/source/+transfer/failmessage.m b/source/+transfer/failmessage.m deleted file mode 100644 index 1dca2c8..0000000 --- a/source/+transfer/failmessage.m +++ /dev/null @@ -1,29 +0,0 @@ -function failmessage -%This throws a fail message to instruct the site on what to do. - -%Einar Heiberg -global DATA - -% Display message -old_dna = DATA.Pref.DoNotAsk; -DATA.Pref.DoNotAsk = false; %Ensure that message box is displayed. -DATA.Buffer.KeyStroke = {}; %Ensure that message box is displayed. - -mymsgbox(dprintf([... - 'Something went wrong! \n\n' ... - 'An error report will be generated after you have clicked OK on \n' ... - 'this message. Please copy errors from the error report and send \n' ... - 'them in an email to support@medviso.com.\n\n' ... - 'We will then look into the source of the problem and assist you as soon as possible.'])); - -flushlog; -if ispc - dos(sprintf('notepad.exe "%s" &',DATA.LogFile)); -else - mymsgbox(dprintf('Log file for this run is %s',DATA.LogFile),'',DATA.GUI.Segment); -end; - - -mybrowser('mailto:support@medviso.com'); - -DATA.Pref.DoNotAsk = old_dna; \ No newline at end of file diff --git a/source/+transfer/getcredsfile.m b/source/+transfer/getcredsfile.m deleted file mode 100644 index 7cdda00..0000000 --- a/source/+transfer/getcredsfile.m +++ /dev/null @@ -1,29 +0,0 @@ -function name = getcredsfile(inpath) -%Returns the name of the credentials file. If not existing, then return -%empty. Function looks in the default directory. If multiple files are -%existing, the return them in a cell array.nn -% -%See also READCREDENTIALS - -%Einar Heiberg - -name = ''; - -if nargin == 0 - f = dir('*.transfercreds'); -else - f = dir([inpath filesep '*.transfercreds']); -end; - -if isempty(f) - return; -end; - -if length(f)>1 - name = cell(1,length(f)); - for loop = 1:length(f) - name{loop} = f(loop).name; - end; -else - name = f(1).name; -end; \ No newline at end of file diff --git a/source/+transfer/getcredsfile.p b/source/+transfer/getcredsfile.p new file mode 100644 index 0000000..840afac Binary files /dev/null and b/source/+transfer/getcredsfile.p differ diff --git a/source/+transfer/gui.m b/source/+transfer/gui.m deleted file mode 100644 index ee54c0b..0000000 --- a/source/+transfer/gui.m +++ /dev/null @@ -1,222 +0,0 @@ -classdef gui < maingui - - methods - - %------------------------------- - function g = gui(programversion) - %------------------------------- - %Constructor - - %Call superclass constructor - g = g@maingui(programversion); - - end - - %---------------------- - function initLogFile(g) - %---------------------- - %This overloaded method sets the name of the log-file. - pathname = g.getpreferencespath; - g.LogFile = [pathname filesep sprintf('segmenttransferlog_%s.log',datestr(now,'yyyymmddHHMMSS'))]; - fid = fopen(g.LogFile,'w'); - if isequal(fid,-1) - myfailed(dprintf('Could not create .log file %s.',g.LogFile)); - else - fclose(fid); %Close the file, to make it empty - g.startlog(g.LogFile); %Start diary. - fprintf(1,'Segment Transfer Version %s\n',g.ProgramVersion); - end; - end - - %--------------------------- - function loadguipositions(g) - %--------------------------- - %Load prestored positions of GUI's. - %Overload this with empty function, do not need to load gui positions - end; - - %---------------------- - function initmaingui(g) - %---------------------- - %Initiates main GUI. Overloads mainGUI method to use Segment-transfer GUI instead - g.GUI.Segment=mygui(['+transfer' filesep 'segmenttransfer.fig']);%Load custom GUI - g.fig = g.GUI.Segment.fig; - g.Handles = killhandles(g.fig,'segment.fig'); - g.ProgramName = 'Segment-Transfer'; - - gui = g.GUI.Segment; - - %Create the progressbar - gui.handles.overallpatch = patch(... - [0 0 0 0],... - [0 1 1 0],... - [1 1 1 1],... - 'parent',gui.handles.overallaxes); - hold(gui.handles.overallaxes,'on'); hold(gui.handles.overallaxes,'on'); - gui.handles.overallline = plot(gui.handles.overallaxes,[0 0 1 1 0],[0 1 1 0 0],'k-'); - hold(gui.handles.overallaxes,'off'); - xlim(gui.handles.overallaxes,[0 1]); - axis(gui.handles.overallaxes,'off'); - set(gui.handles.overalltext,'string',''); - - set(gui.handles.overallline,'visible','off'); - set(gui.handles.overallpatch,'visible','off'); - set(gui.handles.overallaxes,'visible','off'); - - %Create the detail waitbar - gui.handles.detailpatch = patch(... - [0 0 0 0],... - [0 1 1 0],... - [1 1 1 1],... - 'parent',gui.handles.detailaxes); - hold(gui.handles.detailaxes,'on'); - gui.handles.detailline = plot(gui.handles.detailaxes,[0 0 1 1 0],[0 1 1 0 0],'k-'); - hold(gui.handles.detailaxes,'off'); - xlim(gui.handles.detailaxes,[0 1]); - axis(gui.handles.detailaxes,'off'); - - set(gui.handles.detailtext,'string',''); - set(gui.handles.detailline,'visible','off'); - set(gui.handles.detailpatch,'visible','off'); - set(gui.handles.detailaxes,'visible','off'); - - %Ensure that the credentials file exists - if isempty(transfer.getcredsfile) - mywarning(... - ['The credentials file is not installed. This file contains necessary log-in '... - 'information. You should have received this file in email. '... - 'Please contact the study core-lab if you are missing the file, or support@medviso.com. ' ... - 'You will now be prompted to locate the file.']); - - pause(0.1); - - %Ask for file - g.askforfile(); - end; - - if isempty(transfer.getcredsfile) - myfailed('Please fix problem with missing credentials and restart application.'); - end; - - end - - %---------------------- - function inittoolbar(g) %#ok - %---------------------- - %Initiate toolbars. Overloads mainGUI method. - end - - %--------------------------- - function updateicons(g,mode) %#ok - %--------------------------- - %Overloads mainGUI method - - %Reset Tool structure - g.Tools = []; - end - - %------------------ - function askforfile(g) %#ok - %------------------ - %Ask for creds file and copies it to pwd - - [filename,pathname] = myuigetfile('*.transfercreds','Select the file transfercreds file'); - if isequal(pathname,-1) || isequal(filename,-1) - myfailed('Aborted.') - return; - end; - - if ~exist([pathname filesep filename],'file') - myfailed('File does not exist. Aborted.'); - end; - ok = copyfile([pathname filesep filename],[pwd filesep filename]); - if ~ok - myfailed(dprintf('Could not copy file. Folder %s write protected?',pwd)); - else - mymsgbox('File copy successfull.'); - end; - end - - %---------------------- - function updatetitle(g) - %---------------------- - %Updates titleline of main GUI. Overloads method in SegmentGUI - - set(g.fig,'Name',['Segment Transfer v' changelog]); - end - - end - - methods(Static) - - %----------------------- - function dispwelcometext - %----------------------- - %Overloads method in mainGUI - end - - %-------------------- - function versionhello - %-------------------- - %Overloads method in mainGUI - disp(['Segment Transfer v' changelog '.']) - end - - - %---------------------------------------------- - function h = mywaitbarstart(iter,stri,varargin) - %---------------------------------------------- - global DATA - - %Just store it for future work - gui = DATA.GUI.Segment; - gui.numiter = iter; - gui.iter = 0; - gui.detailstri = stri; - - %Update text - set(gui.handles.detailtext,'string',stri); - - %Make it visible - set([... - gui.handles.detailline... - gui.handles.detailpatch ... - gui.handles.detailtext],'visible','on'); - h = []; - end; - - %-------------------------------- - function mywaitbarclose(varargin) - %-------------------------------- - global DATA - - gui = DATA.GUI.Segment; - - %Make it invisible - set([... - gui.handles.detailline... - gui.handles.detailpatch ... - gui.handles.detailtext],'visible','off'); - - end; - - %------------------------------------- - function h = mywaitbarupdate(varargin) - %------------------------------------- - global DATA - - gui = DATA.GUI.Segment; - - gui.iter = gui.iter+1; - f = gui.iter/gui.numiter; - - set(gui.handles.detailpatch,'xdata',[0 0 f f]); - drawnow; - - h = []; - end; - - - end - -end \ No newline at end of file diff --git a/source/+transfer/hash.m b/source/+transfer/hash.m deleted file mode 100644 index bfc4450..0000000 --- a/source/+transfer/hash.m +++ /dev/null @@ -1,79 +0,0 @@ -function h = hash(inp,meth) -% HASH - Convert an input variable into a message digest using any of -% several common hash algorithms -% -% USAGE: h = hash(inp,'meth') -% -% inp = input variable, of any of the following classes: -% char, uint8, logical, double, single, int8, uint8, -% int16, uint16, int32, uint32, int64, uint64 -% h = hash digest output, in hexadecimal notation -% meth = hash algorithm, which is one of the following: -% MD2, MD5, SHA-1, SHA-256, SHA-384, or SHA-512 -% -% NOTES: (1) If the input is a string or uint8 variable, it is hashed -% as usual for a byte stream. Other classes are converted into -% their byte-stream values. In other words, the hash of the -% following will be identical: -% 'abc' -% uint8('abc') -% char([97 98 99]) -% The hash of the follwing will be different from the above, -% because class "double" uses eight byte elements: -% double('abc') -% [97 98 99] -% You can avoid this issue by making sure that your inputs -% are strings or uint8 arrays. -% (2) The name of the hash algorithm may be specified in lowercase -% and/or without the hyphen, if desired. For example, -% h=hash('my text to hash','sha256'); -% (3) Carefully tested, but no warranty. Use at your own risk. -% (4) Michael Kleder, Nov 2005 -% -% EXAMPLE: -% -% algs={'MD2','MD5','SHA-1','SHA-256','SHA-384','SHA-512'}; -% for n=1:6 -% h=hash('my sample text',algs{n}); -% disp([algs{n} ' (' num2str(length(h)*4) ' bits):']) -% disp(h) -% end - -inp=inp(:); -% convert strings and logicals into uint8 format -if ischar(inp) || islogical(inp) - inp=uint8(inp); -else % convert everything else into uint8 format without loss of data - inp=typecast(inp,'uint8'); -end - -% verify hash method, with some syntactical forgiveness: -meth=upper(meth); -switch meth - case 'SHA1' - meth='SHA-1'; - case 'SHA256' - meth='SHA-256'; - case 'SHA384' - meth='SHA-384'; - case 'SHA512' - meth='SHA-512'; - otherwise -end -algs={'MD2','MD5','SHA-1','SHA-256','SHA-384','SHA-512'}; -if isempty(strmatch(meth,algs,'exact')) - error(['Hash algorithm must be ' ... - 'MD2, MD5, SHA-1, SHA-256, SHA-384, or SHA-512']); -end - -% create hash -x=java.security.MessageDigest.getInstance(meth); -x.update(inp); -h=typecast(x.digest,'uint8'); -h=dec2hex(h)'; -if(size(h,1))==1 % remote possibility: all hash bytes < 128, so pad: - h=[repmat('0',[1 size(h,2)]);h]; -end -h=lower(h(:)'); -clear x -return \ No newline at end of file diff --git a/source/+transfer/path2files.m b/source/+transfer/path2files.m deleted file mode 100644 index 4e45c87..0000000 --- a/source/+transfer/path2files.m +++ /dev/null @@ -1,16 +0,0 @@ -function files = path2files(path) -%Return the files in a path - - dd = dir(path); - files = {}; - - for i=1:numel(dd) - if(dd(i).isdir) - continue - end - if isequal(dd(i).name, 'dicom.cache') - continue - end - files(end+1) = {[path dd(i).name]}; - end -end \ No newline at end of file diff --git a/source/+transfer/path2study.m b/source/+transfer/path2study.m deleted file mode 100644 index cef0734..0000000 --- a/source/+transfer/path2study.m +++ /dev/null @@ -1,20 +0,0 @@ -function r = path2study(path) -%Returns a cell array with the paths to studies - tt = dir(path); - r = {}; - for i=1:numel(tt) - if isequal(tt(i).name, '.') - continue - end - if isequal(tt(i).name, '..') - continue - end - if isequal(tt(i).name, '.svn') - continue - end - if not(tt(i).isdir) - continue - end - r{end+1} = transfer.path2files([path filesep tt(i).name filesep]); - end -end \ No newline at end of file diff --git a/source/+transfer/progressbar.m b/source/+transfer/progressbar.m deleted file mode 100644 index d93ebc4..0000000 --- a/source/+transfer/progressbar.m +++ /dev/null @@ -1,11 +0,0 @@ -function progressbar(f,msg) -global DATA - -try - gui = DATA.GUI.Segment; - - set(gui.handles.overalltext,'string',msg); - set(gui.handles.overallpatch,'xdata',[0 0 f f]); - drawnow; -catch %#ok -end; \ No newline at end of file diff --git a/source/+transfer/readcredentials.m b/source/+transfer/readcredentials.m deleted file mode 100644 index 75778db..0000000 --- a/source/+transfer/readcredentials.m +++ /dev/null @@ -1,70 +0,0 @@ -function [study, user, pw, url,pattern] = readcredentials() -%Read the credentials file. - -%Jonatan Wulcan. Modified by Einar Heiberg -name = transfer.getcredsfile; -if isempty(name) - error('SEGMENT:ERROR','Could not find any credentials file.'); -end; - -if iscell(name) - %Found multiple - - %Loop over them to extract site name - sitenames = cell(size(name)); - for loop = 1:length(sitenames) - fid = fopen(name{loop},'rt'); - if isequal(fid,-1) - error('SEGMENT:ERROR','Could not open credentials file.'); - end; - stri = fgetl(fid); - sitenames{loop} = stri; - fclose(fid); - end; - m = mymenu('Select trial.',sitenames{:}); - - if isequal(m,0) - error('SEGMENT:ERROR','User aborted.'); - end; - - name = name{m}; -end; - -fid = fopen(name,'r'); -if fid == -1 - error('SEGMENT:ERROR', sprintf('Couldn''t open %s. Please contact core lab for support.',name)); %#ok -end - -%Read study -stri = fgetl(fid); -if isempty(stri) - error('SEGMENT:ERROR','Could not read study name.'); -end; -study = stri; - -%Read username -stri = fgetl(fid); -if isempty(stri) - error('SEGMENT:ERROR','Could not read user name.'); -end; -user = stri; - -%Read password -stri = fgetl(fid); -if isempty(stri) - error('SEGMENT:ERROR','Could not read password.'); -end; -pw = stri; - -%Read url -stri = fgetl(fid); -if isempty(stri) - error('SEGMENT:ERROR','Could not read URL.'); -end; -url = stri; - -%Read pattern -stri = fgetl(fid); -pattern = stri; - -fclose(fid); \ No newline at end of file diff --git a/source/+transfer/readcredentials.p b/source/+transfer/readcredentials.p new file mode 100644 index 0000000..58ee6f0 Binary files /dev/null and b/source/+transfer/readcredentials.p differ diff --git a/source/+transfer/scaleim.m b/source/+transfer/scaleim.m deleted file mode 100644 index 2b814c5..0000000 --- a/source/+transfer/scaleim.m +++ /dev/null @@ -1,20 +0,0 @@ -function outim = scaleim(im) -%This function scales the image to get good contrast, see autocontrast -%in segment_main for details. - -%Einar Heiberg, inspired by Janes autocontrast implementation - -%Set percentile values, see autocontast -lowerpercentile=0.02; -upperpercentile=0.99; - -sortim = sort(im(:)); -lowerthresh = sortim(round(lowerpercentile*length(sortim))); -upperthresh = sortim(round(upperpercentile*length(sortim))); - -%Cut above/below -outim = max(im,lowerthresh); -outim = min(outim,upperthresh); - -%Normalize between 0..1 -outim = (outim-lowerthresh)/(upperthresh-lowerthresh); diff --git a/source/+transfer/sendfile.m b/source/+transfer/sendfile.m deleted file mode 100644 index 356d805..0000000 --- a/source/+transfer/sendfile.m +++ /dev/null @@ -1,71 +0,0 @@ -classdef sendfile < handle - properties(SetAccess = private, GetAccess = private) - data - bytes_left - chunksize - sendfunc - end - - methods(Access = public) - function self = sendfile(sendfunc) - self.data = struct('data', {}, 'pos', {}, 'fileid', {}); - self.chunksize = 2000000; - self.bytes_left = self.chunksize; - self.sendfunc = sendfunc; - end - - function addfile(self, fileinfo) - f = fopen(fileinfo.name, 'r'); - bytes = fread(f, inf, '*uint8'); - fclose(f); - - data_added = 0; - while data_added ~= numel(bytes) - data_added = data_added + ... - self.add_data(bytes((1+data_added):end), data_added, fileinfo.id); - end - end - - function finalize(self) - self.send(); - end - end - - methods(Access = private) - function send(self) - if(numel(self.data) == 0) - return - end - self.sendfunc(self.data); - clear self.data; - self.data = struct('data', {}, 'pos', {}, 'fileid', {}); - self.bytes_left = self.chunksize; - end - - function data_added = add_data(self, raw_bytes, pos, id) - % Find out how much data we want and b64encode it - data_added = numel(raw_bytes); - bytes = transfer.base64encode(raw_bytes(1:data_added)); - if(numel(bytes) > self.bytes_left) - data_added = floor(self.bytes_left/1.3509)-100; - bytes = transfer.base64encode(raw_bytes(1:data_added)); - end - if(numel(bytes) > self.bytes_left) - error('SEGMENT:PANIC', 'Couldn''t find good size'); - end - - self.data(end+1) = struct(... - 'data', bytes, ... - 'pos', pos, ... - 'fileid', id); - self.bytes_left = self.bytes_left - numel(bytes); - - if(self.bytes_left < 10000) - self.send(); - end - end - end - - methods(Static, Access = public) - end -end \ No newline at end of file diff --git a/source/+transfer/sendmatfile.m b/source/+transfer/sendmatfile.m deleted file mode 100644 index 09bbe11..0000000 --- a/source/+transfer/sendmatfile.m +++ /dev/null @@ -1,27 +0,0 @@ -function sendmatfile(server, study, matfile) - % Get the hash and data - f = fopen(matfile, 'r'); - data = fread(f, inf, '*uint8'); - fclose(f); - h = transfer.hashfile(matfile); - - % Create the file - file_id = server.new_matfile(study, h); - - % Send the acctual file - pos = 1; - chunksize = 524288; - hw = waitbar(0,'Please wait uploading .mat file.'); - while(pos <= numel(data)) - server.update_matfile(file_id, pos-1, ... - transfer.base64encode( ... - data( ... - pos:min([pos+chunksize-1 numel(data)]) ... - ) ... - )); - pos = pos + chunksize; - waitbar(pos/numel(data),hw); - end - close(hw); - server.finalize_matfile(file_id); -end \ No newline at end of file diff --git a/source/+transfer/sendmatfile.p b/source/+transfer/sendmatfile.p new file mode 100644 index 0000000..81c2848 Binary files /dev/null and b/source/+transfer/sendmatfile.p differ diff --git a/source/+transfer/sendserie.m b/source/+transfer/sendserie.m deleted file mode 100644 index 7d405ea..0000000 --- a/source/+transfer/sendserie.m +++ /dev/null @@ -1,34 +0,0 @@ -function sendserie(server, study, desc, files, wbfac) - -serie_id = server.new_serie(desc, study); -wb = wbfac(numel(files), 'Uploading files...'); - -%First upload DICOMS -senddicoms(server, files, wb, serie_id); - -%----------------------------------------------- -function senddicoms(server, files, wb, serie_id) -%----------------------------------------------- -%Send DICOMs (stored in files) to server - -% Create fileinfos -fileinfos = struct('name', {}, 'hash', {}); -for i=1:numel(files) - fileinfos(i) = struct(... - 'name', files{i}, ... - 'hash', transfer.hashfile(files{i})); -end - -% new dicomfiles -fileinfos = server.new_dicomfiles(fileinfos, serie_id); - -% send files -sendfile = transfer.sendfile(@(data) server.update_dicomfile(data)); -for i=1:numel(fileinfos) - sendfile.addfile(fileinfos(i)); - wb.update(); -end -sendfile.finalize(); - -% finalize files -server.finalize_dicomfile({fileinfos.id}); \ No newline at end of file diff --git a/source/+transfer/sendstudy.m b/source/+transfer/sendstudy.m deleted file mode 100644 index 111bb37..0000000 --- a/source/+transfer/sendstudy.m +++ /dev/null @@ -1,36 +0,0 @@ -function didfail = sendstudy(server, series, name, wbfac) -%Send a study, series is a cell array struct of files - -if(numel(series) == 0) - error('SEGMENT:ERROR', 'No series to send'); -end - -%Set up study object -study = server.new_study('N/A', name); - -%Loop over series to send -didfail = false; -for i=1:numel(series) - - %Send serie - try - transfer.sendserie(... - server, study, 'N/A', series{i}, wbfac); - catch me - disp(sprintf('Could not send serie %d',i)); %#ok - mydispexception(me); - didfail = true; - end; - - %Update progress bar - transfer.progressbar(0.3+0.7*i/numel(series),... - sprintf('Sending serie %d/%d',i,numel(series))); -end - -try - server.finalize_study(study); -catch me - disp('Could not finalize study'); - mydispexception(me); - didfail = true; -end; diff --git a/source/+transfer/server.m b/source/+transfer/server.m deleted file mode 100644 index e4163c8..0000000 --- a/source/+transfer/server.m +++ /dev/null @@ -1,311 +0,0 @@ -classdef server < handle - properties(SetAccess = private, GetAccess = private) - user - password - url - end - - methods(Access = public) - function self = server(user, password, url) - self.user = user; - self.password = password; - self.url = url; - end - - function id = new_study(self, uid, name) - r = self.send('new_study', {'uid', uid, 'name', name}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t create study: ' r{1}]); - end - id = r{2}; - end - - function id = new_serie(self, desc, study) - r = self.send('new_serie', {'desc', desc, 'study', study}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t create serie: ' r{1}]); - end - id = r{2}; - end - - function fileinfos = new_dicomfiles(self, fileinfos, serie) - r = self.send('new_dicomfile', {... - 'hash', self.join( {fileinfos.hash} ), ... - 'serie', serie}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t create file: ' r{1}]); - end - ids = self.split(r{2}); - for i=1:numel(ids) - fileinfos(i).id = ids{i}; - end - end - - function update_dicomfile(self, data) - r = self.send('update_dicomfile', {... - 'file', self.join( {data.fileid} ), ... - 'pos', self.join( arrayfun(@(x) {sprintf('%d', x{1})}, {data.pos}) ), ... - 'data', self.join( {data.data} ) ... - } ) ; - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t upload part of file: ' r{1}]); - end - end - - function finalize_dicomfile(self, ids) - r = self.send('finalize_dicomfile', {'file', self.join(ids)}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t finalize dicomfile: ' r{1}]); - end - end - - function id = new_thumbnail(self, thumb_big_hash, thumb_small_hash, thumb_anim_hash, serie, prio) - r = self.send('new_thumbnail', { ... - 'serie', serie, ... - 'hash_big', self.join(thumb_big_hash), ... - 'hash_small', self.join(thumb_small_hash), ... - 'hash_anim', self.join(thumb_anim_hash), ... - 'prio', self.join(prio)}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t create thumbnail: ' r{1}]); - end - id = self.split(r{2}); - end - - function update_thumbnail(self, data, type) - r = self.send('update_thumbnail', {... - 'thumb', self.join( {data.fileid} ), ... - 'type', type, ... - 'pos', self.join( arrayfun(@(x) {sprintf('%d', x{1})}, {data.pos}) )... - 'data', self.join( {data.data} )}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t upload part of thumbnail: ' r{1}]); - end - end - - function finalize_thumbnail(self, id) - r = self.send('finalize_thumbnail', {'thumb', self.join(id)}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t finalize thumbnail: ' r{1}]); - end - end - - function set_thumbnail(self, serie, thumb) - r = self.send('set_thumbnail', ... - {'serie', serie, 'thumb', thumb}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t set thumbnail: ' r{1}]); - end - end - - function finalize_study(self, study) - r = self.send('finalize_study', ... - {'study', study}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t finalize study: ' r{1}]); - end - end - - function study = get_waiting_for_mat(self) - r = self.send('get_waiting_for_mat', {}); - if isequal(r{1}, 'ok') && length(r)>1 - study = r{2}; - elseif isequal(r{1}, 'nothing') - study = []; - elseif isequal(r{1},'noAccess') - error('SEGMENT:ERROR','NoAccess returned. Probably incorrect credentials.'); - else - error('SEGMENT:ERROR','An unknown error occurd while trying to fetch series waiting for mat.'); - end - end - - function [pattern] = get_pattern_for_user(self) - r = self.send('get_pattern_for_user', {}); - if isequal(r{1}, 'ok') && length(r)>1 - pattern = r(2); %return all studies - return; - end; - - if isequal(r{1},'patternNotSet') - error('SEGMENT:ERROR','PatternNotSet returned. Pattern is not set for this user'); - end; - - if isequal(r{1},'noAccess') - error('SEGMENT:ERROR','NoAccess returned. Probably incorrect credentials.'); - end; - - %Should not get here, should return above in ok clause. Throw error. - error('SEGMENT:ERROR','An unknown error occurd while trying to get pattern.'); - - end; - - function [study,names] = get_studies_by_status(self,status) - r = self.send('get_studies_by_status', {'status', status}); - if isequal(r{1}, 'ok') && length(r)>1 - study = r(4:2:end); %return all studies - names = r(3:2:end); %return all names - elseif isequal(r{1}, 'nothing') - study = []; - names = {}; - elseif isequal(r{1},'noAccess') - error('SEGMENT:ERROR','NoAccess returned. Probably incorrect credentials.'); - else - error('SEGMENT:ERROR',sprintf('An unknown error occurd while trying to fetch series %s.',status)); %#ok - end - end; - - function [study,names] = get_studies_by_status_and_scantime(self, status, scantime) - r = self.send('get_studies_by_status_and_scantime', {'status', status, 'scantime', scantime}); - if isequal(r{1}, 'ok') && length(r)>1 - study = r(4:2:end); %return all studies - names = r(3:2:end); %return all names - elseif isequal(r{1}, 'nothing') - study = []; - names = {}; - elseif isequal(r{1},'noAccess') - error('SEGMENT:ERROR','NoAccess returned. Probably incorrect credentials.'); - else - error('SEGMENT:ERROR',sprintf('An unknown error occurd while trying to fetch series %s.',status)); %#ok - end - end; - - function [study,names] = get_waiting_for_consensus(self) - r = self.send('get_waiting_for_consensus', {}); - if isequal(r{1}, 'ok') && length(r)>1 - study = r(4:2:end); %return all studies - names = r(3:2:end); %return all names - elseif isequal(r{1}, 'nothing') - study = []; - names = {}; - elseif isequal(r{1},'noAccess') - error('SEGMENT:ERROR','NoAccess returned. Probably incorrect credentials.'); - else - error('SEGMENT:ERROR','An unknown error occurd while trying to fetch series waiting for consensus.'); - end - end - - function r = get_intresting_series(self, study) - r = self.send('get_intresting_series', {'study', study}); - if not(isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t get intresting series: ' r{1}]); - end - r(1:2) = []; - end - - function r = get_dicom_files(self, series) - %Probably obsoleted??? EH: - r = self.send('get_dicom_files', {'series', series}); - if not(isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t get dicom files: ' r{1}]); - end - r(1:2) = []; - end - - function r = get_mat_files(self, study, owner) - r = self.send('get_mat_files', {'study', study, 'owner', owner}); - if not(isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t get mat files: ' r{1}]); - end - r(1:2) = []; - end - - function r = get_dicom_data(self, dicom) - r = self.rawsend('get_dicom_data', {'dicom', dicom}); - if isempty(r) - error('SEGMENT:ERROR', 'Couldn''t get dicom data'); - end - end - - function id = new_matfile(self, study, hash) - r = self.send('new_matfile', {'study', study, 'hash', hash}); - if not(isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t create new matfile: ' r{1}]); - end - id = r{2}; - end - - function update_matfile(self, id, pos, data) - r = self.send('update_matfile', {'matfile', id, 'pos', sprintf('%d', pos), 'data', data}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t upload part of matfile: ' r{1}]); - end - end - - function update_status(self,id,newstatus) - r = self.send('update_status', ... - {'study', id, 'newstatus', newstatus}); - if not(isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t update status: ' r{1}]); - end - end; - - function finalize_matfile(self, matfile) - r = self.send('finalize_matfile', ... - {'matfile', matfile}); - if(~isequal(r{1}, 'ok')) - error('SEGMENT:ERROR', ['Couldn''t finalize matfile: ' r{1}]); - end - end - - end - - methods(Access = private) - function r = send(self, action, args) - r = self.unpack_result(self.rawsend(action, args)); - %r = self.unpack_result(urlread(self.url, 'post', ... - % [{'user', self.user, 'password', self.password, 'action', action} args])); - end - end - - methods(Access = public) - function r = rawsend(self, action, args) - failed_attempts = 0; - while true - try - r = urlread(self.url, 'post', ... - [{'user', self.user, 'password', self.password, 'action', action} args]); - catch e - if strcmp(e.message, 'Error downloading URL.') - if failed_attempts > 3 - error('SEGMENT:ERROR', 'Couldn''t connect to core lab server'); - else - failed_attempts = failed_attempts + 1; - continue; - end - else - rethrow(e); - end - end - break - end - - end - end - - methods(Static, Access = public) - function r = unpack_result(res) - r = {}; - while(numel(res) ~= 0) - [A, ~, ~, nextindex] = sscanf(res, '%s', 1); - A = A(uint8(A)~=255); %remove uint8(255) from string - r{end+1} = A; - res = res(nextindex:end); - end - end - - function r = join(str_list) - r = ''; - for i=1:numel(str_list) - if i == 1 - r = str_list{1}; - else - r = [r '|' str_list{i}]; - end - end - end - - function r = split(data) - r = regexp(data, '\|', 'split'); - end - end -end \ No newline at end of file diff --git a/source/+transfer/server.p b/source/+transfer/server.p new file mode 100644 index 0000000..b8a2026 Binary files /dev/null and b/source/+transfer/server.p differ diff --git a/source/+transfer/setproxy.m b/source/+transfer/setproxy.m deleted file mode 100644 index 13dae22..0000000 --- a/source/+transfer/setproxy.m +++ /dev/null @@ -1,11 +0,0 @@ -function setproxy() - [h, p] = transfer.findproxy(); - if not(isequal(h, '')) - com.mathworks.mlwidgets.html.HTMLPrefs.setUseProxy(true); - com.mathworks.mlwidgets.html.HTMLPrefs.setProxyHost(h); - com.mathworks.mlwidgets.html.HTMLPrefs.setProxyPort(p); - com.mathworks.mlwidgets.html.HTMLPrefs.setUseProxyAuthentication(false); - else - com.mathworks.mlwidgets.html.HTMLPrefs.setUseProxy(false); - end -end \ No newline at end of file diff --git a/source/+transfer/study.m b/source/+transfer/study.m deleted file mode 100644 index 90fa42e..0000000 --- a/source/+transfer/study.m +++ /dev/null @@ -1,197 +0,0 @@ -classdef study < handle - properties(SetAccess = private, GetAccess = private) - temppath - studypath - waitbar - pattern - newname - end - - methods(Access = public) - - function self = study(path, pattern, waitbar) - - global DATA - - gui = DATA.GUI.Segment; - - self.waitbar = waitbar; - self.pattern = pattern; - - %--- Ask for new name for the study - mymsgbox(dprintf([... - 'You need to give the study a new. Please follow the pattern according to the CRF. '... - 'In this trial the pattern is %s where the characters means: \n\n' ... - 'n any numeric digit (0,1,2,3,4,5,6,7,8,9)\n' ... - 'x any character, (A,B,C....,a,b,c...)\n' ... - 'X (upper case letter). Must be exact this character\n' ... - '0 numerical digit. Must be exactly this digit\n' ... - '- dash\n' ... - ': colon\n' ... - '. point\n'],pattern)); - - docheck = true; - if isempty(pattern) - docheck = false; - pattern = 'Pnnnn'; - end; - - valid = false; - - %Keep asking until a valid name has been found. - while ~valid - s = inputdlg({['Enter new patient name according to the pattern ' pattern]},'Patient Name',1,{pattern}); - if isempty(s) - error('SEGMENT:ERROR','User aborted on naming study.'); - else - self.newname = s{1}; - end; - - %Ensure no uncessesary spaces - self.newname = strtrim(self.newname); - - %--- Check validity of pattern - if docheck - [valid,msg] = transfer.checkpattern(pattern,self.newname); %Throws an error if not matching - if ~valid - mymsgbox(dprintf('Invalid name. Pattern is %s. %s',pattern,msg)); - end; - else - valid = true; - end; - end; - - %Enable the progress bar - set(gui.handles.overallpatch,'visible','on'); - set(gui.handles.overallline,'visible','on'); - set(gui.handles.overalltext,'visible','on'); - - self.temppath = tempname; - mkdir(self.temppath); - - %--- Sort the files (1). - transfer.progressbar(0.1,'Sort and copy files.'); - logargs.recurse = true; - logargs.anonym = false; - logargs.stable = false; % but slow - logargs.keepname = false; - logargs.makethumbs = false; - logargs.usedesc = true; % sort by series description - dicomsorter('sortit', path, 1, self.temppath, [], logargs); - delete([self.temppath filesep 'log.txt']); - - % Check that we only have one study and get the patientpath name - tt = dir(self.temppath); - numfolders = sum(cat(1,tt(:).isdir)); - - if isequal(numfolders,2) - error('SEGMENT:ERROR', 'Didn''t find any valid DICOM files in choosen folder'); - end - - %Make a list of studies - studies = []; - studies.patient = []; - studies.studydate = []; - studies.folder = []; - studies.series = []; - - numstudies = 0; - for loop = 1:length(tt) - if tt(loop).isdir && (~isequal(tt(loop).name,'.')) && (~isequal(tt(loop).name,'..')) - %Folder => check for studies - - %get files & folders - f = dir([self.temppath filesep tt(loop).name]); - - for sloop = 1:length(f) - if f(sloop).isdir && (~isequal(f(sloop).name,'.')) && (~isequal(f(sloop).name,'..')) - %Add to list of studies - if isempty(strfind(f(sloop).name,'20XX-XX-XX')) - %Ignored study without valid dates - numstudies = numstudies+1; - studies(numstudies).patient = tt(loop).name; %#ok - studies(numstudies).studydate = f(sloop).name; %#ok - studies(numstudies).folder = [self.temppath filesep tt(loop).name filesep f(sloop).name]; %#ok - - %Find number of series - fs = dir(studies(numstudies).folder); - studies(numstudies).series = sum(cat(1,fs(:).isdir))-2; %#ok - - if studies(numstudies).series<0 - studies(numstudies).series = 0; %#ok - end; - - end; - end; - - end; %Loop over studies - end; %Valid patient - end; %Loop over patients - - if numstudies == 0 - error('ERROR:SEGMENT', 'Found no studies.'); - end; - - if numstudies>1 - mywarning('Detected multiple studies. This should normally not occur.'); - - %Create a menu structure - studycell = cell(1,length(studies)); - for loop = 1:length(studycell) - studycell{loop} = sprintf('Patient:%s Date:%s Series:%d',studies(loop).patient,studies(loop).studydate,studies(loop).series); - end; - - selstudy = mymenu('Select which study to take',studycell{:}); - if isequal(selstudy,0) - error('SEGMENT:ERROR', 'Aborted when chosing which study to take.'); - end; - - if ~yesno(dprintf('Selected study ''%s''. Are you sure?',studycell{selstudy})) - error('SEGMENT:ERROR', 'Aborted when confirming which patient to upload.'); - end; - - else - selstudy = 1; %There was only one... - end; - - self.studypath = studies(selstudy).folder; - - %--- Anonymize (2) - transfer.progressbar(0.2,'Anonymizing data.'); - - anonsilent = true; - anonwaitbar = true; - dicomanonymize(self.studypath, self.newname, anonsilent, anonwaitbar); %Need only to sort the study path - disp(sprintf('Sorted folder was:%s', self.studypath)); - - %Rename the folder - oldfolder = [self.temppath filesep studies(selstudy).patient]; - newfolder = [self.temppath filesep self.newname ]; - - disp(sprintf('Renaming the folder to %s',newfolder)); - - [ok,msg] = movefile(oldfolder, newfolder); - if ~ok && ~strcmp(oldfolder,newfolder) - disp(msg); - error('SEGMENT:ERROR','Could not rename folder.'); - end; - - %Assign the newly renamed folder. - self.studypath = [self.temppath filesep self.newname filesep studies(selstudy).studydate]; - end - - function p = getpath(self) - p = self.studypath; - end - - function n = getname(self) - n = self.newname; - end - - function delete(self) - w = self.waitbar(1, 'Clearing up temporary files...'); %#ok - transfer.deltree(self.temppath); - clear w; - end - end -end \ No newline at end of file diff --git a/source/+transfer/thumbnails.m b/source/+transfer/thumbnails.m deleted file mode 100644 index 272b5dd..0000000 --- a/source/+transfer/thumbnails.m +++ /dev/null @@ -1,184 +0,0 @@ -classdef thumbnails < handle - properties(SetAccess = private, GetAccess = private) - temppath - files - studyuid - description - patname - wbfac - didfail - time - sequencename - venc - docleanup = true; - end - - methods(Access = public) - function self = thumbnails(files, wbf) - self.wbfac = wbf; - wb = self.wbfac(4, 'Generating thumbnails...'); - self.temppath = tempname; - mkdir(self.temppath); - - % Load the data - loader = segloader(); - loader.adddicomfiles(files); - - wb.update(); - - self.didfail = false; - - % May throw exception - [~, data] = loader.render('', []); - - wb.update(); - - % Get the uid, the patient name and the description - self.studyuid = data(1).preview.StudyUID; - self.patname = data(1).preview.PatientInfo.Name; - if (~isfield(data(1).preview,'SequenceName') || strcmp(strtrim(data(1).preview.SequenceName), '')) && (~isfield(data(1).preview,'SeriesDescription') || strcmp(strtrim(data(1).preview.SeriesDescription), '')) - self.description = 'No description'; - self.sequencename = 'No sequence name'; - elseif ~isfield(data(1).preview,'SequenceName') || strcmp(strtrim(data(1).preview.SequenceName), '') - self.description = strtrim(data(1).preview.SeriesDescription); - self.sequencename = 'No sequence name'; - else - t = data(1).preview.AcquisitionTime; - hours = floor(t/3600); - minutes = floor((t-hours*3600)/60); - seconds = floor(t-hours*3600-minutes*60); - self.time = sprintf(... - '%02d:%02d:%02d', ... - hours, minutes, seconds); - self.description = strtrim(data(1).preview.SeriesDescription); - self.sequencename = strtrim(data(1).preview.SequenceName); - end - if size(data(1).IM, 5) ~= 1 - self.description = [self.description ' VENC data is present']; - end - - self.files = {}; - picnum = 0; - - %Loop over rendered stacks - for no = 1:numel(data) - imsz = size(data(no).IM); - if numel(imsz) < 5 - imsz(5) = 1; - if numel(imsz) < 4 - imsz(4) = 1; - end - end - - % Get the thumbnails - frames = imsz(3); - slices = imsz(4); - if frames>30 - %If more than 30 frames, then take middle, else take first. This is - %then a good guess to get enddiastole. - timeslice = round((imsz(3)+1)/2); - else - timeslice = 1; - end; - - %Assign to wholepic. - %If few timeframes, treat as slices - if frames < 4 && slices == 1 - imsz = [imsz(1:2) 1 imsz(3) imsz(5)]; - wholepic = reshape(data(no).IM,imsz); - frames = 1; - slices = imsz(4); - else - wholepic = data(no).IM; - end - - %--- Automatically crop the data if timeresolved. - roisizeslice = 300; %mm - roisizestack = 250; %mm - if (slices>1) && (frames>15) - xsize = roisizestack/data(no).preview.ResolutionX; - ysize = roisizestack/data(no).preview.ResolutionY; - wholepic = autocrop(wholepic,xsize,ysize); - elseif (frames>15) - xsize = roisizeslice/data(no).preview.ResolutionX; - ysize = roisizeslice/data(no).preview.ResolutionY; - wholepic = autocrop(wholepic,xsize,ysize); - end; - - %Loop over slices - for i=1:size(wholepic, 4) - picnum = picnum + 1; - - %Extract data - pic = wholepic(:, :, timeslice, i); - - %Autocontrast of the image - pic = transfer.scaleim(pic); - - %Generate stationary thumbnails - imwrite(pic, sprintf('%s%sthumb-%d-big.jpg', self.temppath, filesep, picnum)); - pic_small = imresize(pic, [128 round(128*size(pic,2)/size(pic,1))]); - imwrite(pic_small, sprintf('%s%sthumb-%d-small.jpg', self.temppath, filesep, picnum)); - - %Generate animations - pic = transfer.scaleim(wholepic(:,:,:,i)); - pic = uint8(floor(pic*255)); - createanimgif(pic,sprintf('%s%sthumb-%d-anim.gif', self.temppath, filesep, picnum)); - - %Send the files - self.files{end+1} = {... - sprintf('%s%sthumb-%d-big.jpg',self.temppath, filesep, picnum), ... - sprintf('%s%sthumb-%d-small.jpg',self.temppath, filesep, picnum), ... - sprintf('%s%sthumb-%d-anim.gif',self.temppath, filesep, picnum)}; - end - end - - wb.update(); - end - - function r = getthumbs(self) - r = self.files; - end - - function r = getstudyuid(self) - r = self.studyuid; - end - - function r = getstudyname(self) - r = self.patname; - end - - function r = getdescription(self) - r = self.description; - end - - function delete(self) - if self.docleanup - transfer.deltree(self.temppath); - end - end - - function r = ok(self) - r = ~self.didfail; - end; - - function r = getsequence(self) - r = self.sequencename; - end - - function r = gettime(self) - r = self.time; - end - - function r = getvenc(self) - r = self.venc; - end - - function donotcleanup(self) - self.docleanup = false; - end - - - end - -end \ No newline at end of file diff --git a/source/+transfer/uploadcurrent_Callback.m b/source/+transfer/uploadcurrent_Callback.m deleted file mode 100644 index 6ed92da..0000000 --- a/source/+transfer/uploadcurrent_Callback.m +++ /dev/null @@ -1,120 +0,0 @@ -function uploadcurrent_Callback -%uploadcurrent_Callback Uploads the current study (i.e matfile) to core -%lab features. - -%Jonatan Wulcan, modified by Einar Heiberg - -global DATA SET - -if isempty(SET) - myfailed('No data to upload'); - return -end - -% Get the study id -if (not(isfield(SET(1), 'transferid'))) || isempty(SET(1).transferid) - myfailed('Couldn''t find Transfer id. The current stack must originate from the Transfer system'); - return -end - -idstr = SET(1).transferid; -spaceloc = regexp(idstr,'[ ]'); -if length(spaceloc) ~= 1 - myfailed('Bad format in transferid'); - return -end -study_id = idstr(1:spaceloc-1); -project_url = idstr(spaceloc+1:end); - -% Save matfile -filename = 'transfer-temp.mat'; -matfile = [getpreferencespath filesep filename]; -topatientdatabase = false; -h = msgbox('Storing file to disk. Please wait.'); -fail = filemenu('saveallas_helper',getpreferencespath,filename,topatientdatabase); -try - close(h); -catch %#ok -end; - -if fail - myfailed('Couldn''t save. Aborting.'); - return; -end; - -try - - try - [~, user, pw, url] = transfer.readcredentials(); - catch me - mydispexception(me); - myfailed('Could not find any credential files.'); - return; - end; - - match_url = url; - - %Remove http:// - if isequal(findstr(match_url,'http://'),1) %#ok<*FSTR> - match_url = match_url(8:end); - end; - - %Remove www. - if isequal(findstr(match_url,'www.'),1) - match_url = match_url(5:end); - end; - - %Remove http:// - if isequal(findstr(project_url,'http://'),1) - project_url = project_url(8:end); - end; - - %Remove www. - if isequal(findstr(project_url,'www.'),1) - project_url = project_url(5:end); - end; - - while ~strcmp(match_url,project_url) - myfailed(dprintf(... - 'Project URL does not match origin, You are trying to upload to wrong trial! \n\nUploading to %s and trial originated from %s.',... - url,project_url)); - - [~, user, pw, url, ~] = transfer.readcredentials(); - - match_url = url; - - %Remove http:// - if isequal(findstr(match_url,'http://'),1) - match_url = match_url(8:end); - end; - - %Remove www. - if isequal(findstr(match_url,'www.'),1) - match_url = match_url(5:end); - end; - - end -catch %#ok - return -end - -try - s = transfer.server(user, pw, url); - transfer.sendmatfile(s, study_id, matfile); -catch e - if strcmp(e.identifier, 'SEGMENT:ERROR') - myfailed(e.message); - return - else - rethrow(e); - end -end - -% Delete matfile -delete(matfile); - -% Display message -old_dna = DATA.Pref.DoNotAsk; -DATA.Pref.DoNotAsk = false; -mymsgbox('Upload completed successfully!'); -DATA.Pref.DoNotAsk = old_dna; diff --git a/source/+transfer/uploadcurrent_Callback.p b/source/+transfer/uploadcurrent_Callback.p new file mode 100644 index 0000000..c6b57d2 Binary files /dev/null and b/source/+transfer/uploadcurrent_Callback.p differ diff --git a/source/+transfer/uploaddicoms_Callback.m b/source/+transfer/uploaddicoms_Callback.m deleted file mode 100644 index 2938998..0000000 --- a/source/+transfer/uploaddicoms_Callback.m +++ /dev/null @@ -1,103 +0,0 @@ -function uploaddicoms_Callback -%This function upload DICOM files to central image repository. - -%Written by Jonatan Wulcan. Commented and modified by Einar Heiberg - -global DATA - -%In the previous version it asked from where to upload data. Now assume and -%ask. - -%Find folder of CD-ROM -pathname = myuigetdir('D:','Select the CD-ROM drive.'); - -if isequal(pathname,0) - myfailed('Aborted.'); - return; -end; - -%Check if folder containing DICOMS -f = dir(pathname); -numdicomfolders = 0; -dicomfolder = pathname; -for loop = 1:length(f) - if f(loop).isdir - if ~isempty(strfind(lower(f(loop).name),'dicom')) - numdicomfolders = numdicomfolders+1; - dicomfolder = f(loop).name; - end; - end; -end; - -%If found only one then -if numdicomfolders == 1 - if yesno('Found one folder named ''dicom''. Do you want to restrict to this folder? (recommended)'); - pathname = [pathname filesep dicomfolder]; - else - disp('Taking whole CD.'); - end; -end; - -try - wb = @(n, msg) transfer.waitbar(n, msg); - [~, user, pw, url, pattern] = transfer.readcredentials(); -catch me - disp('Could not read credential file.'); - mydispexception(me); - transfer.failmessage; - return; %Since fatal -end; - -try - %Create Server object - s = transfer.server(user, pw, url); -catch me - disp('Could not create server object.'); - mydispexception(me); - transfer.failmessage; - return; %Since fatal -end; - -try - %Prepare the study (sort and anonymize) - study = transfer.study(pathname, pattern, wb); -catch me - disp('Could not prepare the study (sort & anonymize)'); - mydispexception(me); - transfer.failmessage; - return; %Since fatal -end; - -try - %Send the study - disp('Starting to send studies.'); - transfer.progressbar(0.3,'Transfering studies.'); - didfail = transfer.sendstudy(s, transfer.path2study(study.getpath), ... - study.getname, wb); -catch me - mydispexception(me); - transfer.failmessage; - return; -end; - -try - clear study -catch me - disp('Could not clear study.'); - mydispexception(me); - transfer.failmessage; -end - -% Display message -old_dna = DATA.Pref.DoNotAsk; -DATA.Pref.DoNotAsk = false; %Ensure that message box is displayed. -DATA.Buffer.KeyStroke = {}; %Ensure that message box is displayed. - -if ~didfail - mymsgbox('Upload completed successfully!'); -else - mymsgbox('Files uploaded. Errors were detected.!'); - transfer.failmessage; -end; -DATA.Pref.DoNotAsk = old_dna; - diff --git a/source/+transfer/viewcomments.m b/source/+transfer/viewcomments.m deleted file mode 100644 index 56136da..0000000 --- a/source/+transfer/viewcomments.m +++ /dev/null @@ -1,44 +0,0 @@ -function viewcomments -% View all comments on active image stacks - -%Nils Lundahl - -%Modified with fixcommentstri by Einar Heiberg - -global SET - -if ~isfield(SET,'Comment') || isempty([SET.Comment]) - myfailed('No comments available') - return -end - -stri = ''; -%Loop over all image stacks -for no = 1:numel(SET) - nostri = ''; - if ~isempty(SET(no).Comment) - comments = SET(no).Comment; - nostri = dprintf('Comments on image stack %d:\n\n',no); - for cmt = comments - txt = sprintf('%s @ %s\n%s\n\n',cmt.Username,cmt.Time,fixcommentstri(cmt.Text)); - nostri = [nostri txt]; - end - end - stri = [stri nostri]; -end - -msgbox(stri,'Comments') - -%------------------------------------------ -function commentstri = fixcommentstri(stri) -%------------------------------------------ -%Ensures that commentstri is a vector of chars. - -if size(stri,1)>1 - commentstri = ''; - for loop = 1:size(stri,1) - commentstri = [commentstri sprintf('\n') stri(loop,:)]; %#ok - end; -else - commentstri = stri; -end; \ No newline at end of file diff --git a/source/+transfer/viewcomments.p b/source/+transfer/viewcomments.p new file mode 100644 index 0000000..965fb36 Binary files /dev/null and b/source/+transfer/viewcomments.p differ diff --git a/source/+transfer/waitbar.m b/source/+transfer/waitbar.m deleted file mode 100644 index adc8c4e..0000000 --- a/source/+transfer/waitbar.m +++ /dev/null @@ -1,25 +0,0 @@ -classdef waitbar < handle - properties(SetAccess = private, GetAccess = private) - h - end - - methods(Access = public) - function self = waitbar(n, msg) - if n==1 - self.h = mywaitbarstart(2, msg); - mywaitbarupdate(self.h); - else - self.h = mywaitbarstart(n, msg); - end - end - - function update(self) - self.h = mywaitbarupdate(self.h); - end - - function delete(self) - mywaitbarclose(self.h); - flushlog; - end - end -end \ No newline at end of file diff --git a/source/+translation/dictionary.m b/source/+translation/dictionary.m index e1165c9..991f566 100644 --- a/source/+translation/dictionary.m +++ b/source/+translation/dictionary.m @@ -4,14 +4,14 @@ % English string if no translation is available global DATA -persistent labels %#ok +persistent labels if nargin < 3 fromlanguage = 'English'; end if nargin < 2 - if ~isempty(DATA) && isfield(DATA.Pref,'Language') + if ~isempty(DATA) && isprop(DATA,'Pref') && isfield(DATA.Pref,'Language') language = DATA.Pref.Language; else language = 'English'; @@ -24,11 +24,34 @@ end if isempty(labels) - load(fullfile('+translation','dictionary.mat'),'labels') + if isdeployed + transpath = 'dictionary.mat'; + else + transpath = fullfile([DATA.SegmentFolder filesep '+translation'],'dictionary.mat'); + end + load(transpath,'labels') +end + +dictind = find(strcmp(stri,{labels(:).(fromlanguage)}),1); +% if ~isempty(dictind) && isfield(labels,language) && ... +% ~isempty(labels(dictind).(language)) +% outstri = labels(dictind).(language); +% end + +% new implementation that if the value does not exist in one language it is +% searched in the english dictionary since it might be an enlish wording +if isempty(dictind) + % try to find index in the english value + dictind = find(strcmp(stri,{labels(:).English}),1); +end +if ~isempty(dictind) + %translate if the value is found either in fromlanguage or in the english + if isfield(labels,language) && ~isempty(labels(dictind).(language)) + % set value to the found value in the language + outstri = labels(dictind).(language); + else + % set value to the english one + outstri = labels(dictind).English; + end end -dictind = find(strcmp(stri,{labels.(fromlanguage)}),1); -if ~isempty(dictind) && isfield(labels,language) && ... - ~isempty(labels(dictind).(language)) - outstri = labels(dictind).(language); -end \ No newline at end of file diff --git a/source/+translation/dictionary.mat b/source/+translation/dictionary.mat index 6d52005..50a0016 100644 Binary files a/source/+translation/dictionary.mat and b/source/+translation/dictionary.mat differ diff --git a/source/+translation/translatealllabels.m b/source/+translation/translatealllabels.m index 53a8865..f887eca 100644 --- a/source/+translation/translatealllabels.m +++ b/source/+translation/translatealllabels.m @@ -5,34 +5,106 @@ function translatealllabels(handle,fromlanguage) fromlanguage = 'English'; end if isa(DATA,'maingui') && isfield(DATA.Pref,'Language') && ~strcmp(DATA.Pref.Language,fromlanguage) - dotranslate(handle,DATA.Pref.Language,fromlanguage); + translateall(handle,DATA.Pref.Language,fromlanguage); +end +%------------------------------------------------- +function translateall(handle,language,fromlanguage) +%------------------------------------------------- + +switch handle.Type + case 'figure' + propertylist = {'Name'}; + case 'uimenu' + propertylist = {'Label','Text'}; + case 'uipanel' + propertylist = {'Title'}; + case 'axes' + propertylist = {'Title','Xlabel','YLabel','Label'}; + case 'uicontrol' + propertylist = {'String','Tooltip'}; + case 'uibuttongroup' + propertylist = {'Title','Tooltip'}; + otherwise + propertylist = {}; +end +if ~isempty(propertylist) + alltext = get(handle,propertylist); + for ind = 1:numel(alltext) + % get and translate only the translatable properties + txt = alltext{ind}; + if ~isempty(txt) + if ischar(txt) + set(handle,propertylist{ind},translation.dictionary(txt,language,fromlanguage)); + elseif iscell(txt) + for j = 1:numel(txt) + if ischar(txt{j}) && ~isempty(txt{j}) + txt{j} = translation.dictionary(txt{j},language,fromlanguage); + end + end + set(handle,propertylist{ind},txt); + end + end + end +end +kids = get(handle, 'Children'); +for i = 1:numel(kids) + translateall(kids(i),language,fromlanguage); end %------------------------------------------------- function dotranslate(handle,language,fromlanguage) %------------------------------------------------- -hstruct = get(handle); -fnames = fieldnames(hstruct); -propertylist = {'Name','String','Label','Title','XLabel','YLabel','TooltipString'}; -plist = intersect(fnames,propertylist); -for i = 1:numel(plist) - p = plist{i}; - txt = hstruct.(p); - if ~isempty(txt) - if ischar(txt) - set(handle,p,translation.dictionary(txt,language,fromlanguage)); - elseif iscell(txt) - for j = 1:numel(txt) - if ischar(txt{j}) && ~isempty(txt{j}) - txt{j} = translation.dictionary(txt{j},language,fromlanguage); +propertylist = {'Name','String','Label','Title','XLabel','YLabel','TooltipString','Text'}; +for i = 1:numel(propertylist) + p = propertylist{i}; + try + + txt = get(handle,p); + if ~isempty(txt) + if ischar(txt) + set(handle,p,translation.dictionary(txt,language,fromlanguage)); + elseif iscell(txt) + for j = 1:numel(txt) + if ischar(txt{j}) && ~isempty(txt{j}) + txt{j} = translation.dictionary(txt{j},language,fromlanguage); + end end + set(handle,p,txt); end - set(handle,p,txt); end + catch end end -kids = hstruct.Children; +kids = handle.Children; for i = 1:numel(kids) dotranslate(kids(i),language,fromlanguage); -end \ No newline at end of file +end + + +% hstruct = get(handle); +% fnames = fieldnames(hstruct); +% propertylist = {'Name','String','Label','Title','XLabel','YLabel','TooltipString','Text'}; +% plist = intersect(fnames,propertylist); +% for i = 1:numel(plist) +% p = plist{i}; +% txt = hstruct.(p); +% if ~isempty(txt) +% if ischar(txt) +% set(handle,p,translation.dictionary(txt,language,fromlanguage)); +% elseif iscell(txt) +% for j = 1:numel(txt) +% if ischar(txt{j}) && ~isempty(txt{j}) +% txt{j} = translation.dictionary(txt{j},language,fromlanguage); +% end +% end +% set(handle,p,txt); +% end +% end +% end +% +% kids = hstruct.Children; +% for i = 1:numel(kids) +% dotranslate(kids(i),language,fromlanguage); +% end + diff --git a/source/+translation/uniquephrases.p b/source/+translation/uniquephrases.p new file mode 100644 index 0000000..9e572cb Binary files /dev/null and b/source/+translation/uniquephrases.p differ diff --git a/source/+straintagging/CardiacMotion64.exe b/source/CardiacMotion64.exe similarity index 100% rename from source/+straintagging/CardiacMotion64.exe rename to source/CardiacMotion64.exe diff --git a/source/Docs/installationmanual.pdf b/source/Docs/installationmanual.pdf deleted file mode 100644 index 1bd2b16..0000000 Binary files a/source/Docs/installationmanual.pdf and /dev/null differ diff --git a/source/Docs/manual.pdf b/source/Docs/manual.pdf deleted file mode 100644 index d30eed9..0000000 Binary files a/source/Docs/manual.pdf and /dev/null differ diff --git a/source/Docs/techmanual.pdf b/source/Docs/techmanual.pdf deleted file mode 100644 index 5ea8ef4..0000000 Binary files a/source/Docs/techmanual.pdf and /dev/null differ diff --git a/source/LVrotation.m b/source/LVrotation.m index fbe3c03..52d3221 100644 --- a/source/LVrotation.m +++ b/source/LVrotation.m @@ -11,7 +11,7 @@ %------------ -function init +function init %#ok %------------ %open the gui to define LV rotation global DATA NO SET @@ -23,7 +23,7 @@ %set rotation and slice set(gui.handles.rotationslider,'value',SET(gui.no).SectorRotation); -set(gui.handles.slicetext,'String',sprintf('Slice %d',gui.slice)); +set(gui.handles.slicetext,'String',dprintf('Slice %d',gui.slice)); if SET(NO).ZSize > 1 set(gui.handles.sliceslider,'Min',1,'Max',... SET(NO).ZSize,'Value',SET(NO).ZSize-gui.slice+1,'SliderStep',... @@ -32,7 +32,7 @@ set(gui.handles.sliceslider,'Visible','off'); set(gui.handles.slicetext,'Visible','off'); end - +segment('recursekeypressfcn',gui.fig,@(hObject,eventdata)LVrotation('keypressed',eventdata)) %plot image plotimage; @@ -43,6 +43,67 @@ ok_Callback; end +%-------------------------- +function requestfocus +%-------------------------- +global DATA +gui = DATA.GUI.LVrotation; +warning off +jFig = get(gui.fig,'JavaFrame'); +jFig.requestFocus; +warning on; + +%------------------------- +function keypressed(evt) %#ok +%------------------------- +%%Keypress function +global DATA +gui = DATA.GUI.LVrotation; +% take away focus from sliders +requestfocus; +switch evt.Key + case {'downarrow','uparrow'} + %move slice + oldvalue = mygetslider(gui.handles.sliceslider); + h = gui.handles.sliceslider; + stepvalue = (h.Max - h.Min)*h.SliderStep(1); + if contains(evt.Key,'up') + newvalue = oldvalue + stepvalue; + else + newvalue = oldvalue - stepvalue; + end + if newvalue > h.Min && newvalue < h.Max + gui.handles.sliceslider.Value = newvalue; + elseif newvalue > h.Max + gui.handles.sliceslider.Value = h.Max; + elseif newvalue < h.Min + gui.handles.sliceslider.Value = h.Min; + end + sliceslider_Callback + + + case {'rightarrow','leftarrow'} + oldvalue = mygetslider(gui.handles.rotationslider); + h = gui.handles.rotationslider; + stepvalue = (h.Max - h.Min)*h.SliderStep(1); + if contains(evt.Key,'right') + newvalue = oldvalue + stepvalue; + else + newvalue = oldvalue - stepvalue; + end + if newvalue > h.Min && newvalue < h.Max + gui.handles.rotationslider.Value = newvalue; + elseif newvalue > h.Max + gui.handles.rotationslider.Value = h.Max; + elseif newvalue < h.Min + gui.handles.rotationslider.Value = h.Min; + end + rotationslider_Callback + + otherwise + return + +end %----------------- function plotimage @@ -70,19 +131,19 @@ [endox,endoy] = calcfunctions('resamplemodel',SET(gui.no).EndoX(:,tf,gui.slice),SET(gui.no).EndoY(:,tf,gui.slice),DATA.Pref.RadialProfiles); if ~isempty(SET(gui.no).EpiX) [epix,epiy] = calcfunctions('resamplemodel',SET(gui.no).EpiX(:,tf,gui.slice), SET(gui.no).EpiY(:,tf,gui.slice),DATA.Pref.RadialProfiles); - end; + end else endox = SET(gui.no).EndoX(:,tf,gui.slice); endoy = SET(gui.no).EndoY(:,tf,gui.slice); if ~isempty(SET(gui.no).EpiX) epix = SET(gui.no).EpiX(:,tf,gui.slice); epiy = SET(gui.no).EpiY(:,tf,gui.slice); - end; -end; + end +end if isempty(SET(gui.no).EpiX) epix = NaN; epiy = NaN; -end; +end %Plot contours hold(gui.handles.imageaxes,'on'); @@ -135,15 +196,16 @@ %---------------------------- -function sliceslider_Callback %#ok +function sliceslider_Callback %---------------------------- %Callback for slider to toggle slice global DATA SET gui = DATA.GUI.LVrotation; +requestfocus; gui.slice = SET(gui.no).ZSize-round(mygetvalue(gui.handles.sliceslider))+1; set(gui.handles.sliceslider,'Value',round(mygetvalue(gui.handles.sliceslider))); -set(gui.handles.slicetext,'String',sprintf('Slice %d',gui.slice)); +set(gui.handles.slicetext,'String',dprintf('Slice %d',gui.slice)); plotimage; @@ -154,6 +216,7 @@ global DATA SET gui = DATA.GUI.LVrotation; +requestfocus; v = get(gui.handles.rotationfromannotationcheckbox,'value'); if v @@ -180,13 +243,13 @@ for loop = 1:length(SET(no).Point.Z) if isequal(SET(no).Point.Label{loop},'RV insertion') || isequal(SET(no).Point.Label{loop},'P1')|| isequal(SET(no).Point.Label{loop},'P2') slices(SET(no).Point.Z(loop)) = true; - end; -end; + end +end %Find slices pos = find(slices); if isempty(pos) - mywarning(sprintf('No RV points found. Current sector rotation is %0.5g',SET(no).SectorRotation)); + mywarning(dprintf('No RV points found. Define two RV annotation points.')); return end pos = reportbullseye('sectorrotationhelper',no); @@ -210,7 +273,7 @@ reportbullseye('startbullseye'); %------------------------ -function cancel_Callback +function cancel_Callback %#ok %----------------------- %cancel the analysis and close the LV rotation interface close_Callback; diff --git a/source/S.p b/source/S.p index 5ec35d2..f8f3044 100644 Binary files a/source/S.p and b/source/S.p differ diff --git a/source/SegmentMeasurements.txt b/source/SegmentMeasurements.txt deleted file mode 100644 index 8b662fb..0000000 --- a/source/SegmentMeasurements.txt +++ /dev/null @@ -1,78 +0,0 @@ -#;This is a comment line no semicolon in the line and end line with one; - -#;First argument is mode as used by the parser, i.e LV/RV/ROI/Scar; - -#;Second argument is type of specification; -#; - mm is measurement; -#; - roi is roi; -#; - sp is special (more flexibility, see below); -#; - ta is graphical description of how the table should look like; -#; ta has a special syntax; - -#;Third argument is code in export; - -#;Fourth argument is short name (displayed); - -#;Fith argument is long name (displayed); - -#;Sixth argument is 1 if show in panel; - -#;Seventh argument is 1 if show in report (not implemented, but needs to be 1); - -#;Eight argument (sp only) is unit; - -#;Nineth argument (sp only) Matlab expression of what to output; - -#;Flow is outputed as CODE_NET,_FWD,_BKWD,_MF,_PEAK,_MEANVEL,_PEAKVEL,_SV,_DIS; - -#;For ta the arguments are in order; -#;- Code; -#;- Title; -#;- Unused; -#;- 1; -#;- 1; -#;- Number of columns; -#;- Number of values; -#;- Vector of column sizes; - - -#;volumes tables; - -#;LV; -LV;ta;LVTable;LV stack X;;1;1;2;1;[0.65 0.35]; -LV;sp;LVM; ED/ES LVM; 1;1;1;g;; -LV;sp;LVEDV; LV-EDV; 1;1;1;ml;; -LV;sp;LVESV; LV-ESV; 1;1;1;ml;; -LV;sp;LVSV; LV-SV; 1;1;1;ml;; -LV;sp;LVEF; LV-EF; 1;1;1;%;; -LV;sp;LVHR; HR; 1;1;1;bpm;; - -#;RV; -RV;ta;RVTable;RV stack X;;1;1;2;1;[0.65 0.35]; -RV;sp;RVM; ED/ES RVM; 1;1;1;g;; -RV;sp;RVEDV; RV-EDV; 1;1;1;ml;; -RV;sp;RVESV; RV-ESV; 1;1;1;ml;; -RV;sp;RVSV; RV-SV; 1;1;1;ml;; -RV;sp;RVEF; RV-EF; 1;1;1;%;; -RV;sp;RVHR; HR; 1;1;1;bpm;; - - - -#;flow tables; - -#;Flow table; -Flow;ta;FlowTable;Flow stack X;;1;1;2;1;[0.65 0.35]; -Flow;sp;ROI; ROI; ROI;1;1;;; -Flow;sp;Netvol; Net; 1;1;1;ml;; -Flow;sp;Forward; Forward; 1;1;1;ml;; -Flow;sp;Backward; Backward; 1;1;1;ml;; -Flow;sp;Regfrac; Regurg. frac;1;1;1;%;; -Flow;sp;FlowHR; HR; 1;1;1;bpm;; - - -#;measurement tables; - -#;Measurement table; -Measurement;ta;MeasurementTable;Measurement stack X;;1;1;2;1;[0.6 0.4]; -Measurement;sp;m1; m1; 1;1;1;g;; -Measurement;sp;m2; m2; 1;1;1;%;; \ No newline at end of file diff --git a/source/addcomment.fig b/source/addcomment.fig index 0d848f7..f8a927d 100644 Binary files a/source/addcomment.fig and b/source/addcomment.fig differ diff --git a/source/addextramenuitems.p b/source/addextramenuitems.p new file mode 100644 index 0000000..9daab90 Binary files /dev/null and b/source/addextramenuitems.p differ diff --git a/source/adminrequirement.m b/source/adminrequirement.m index 61ac2a7..1705695 100644 --- a/source/adminrequirement.m +++ b/source/adminrequirement.m @@ -1,5 +1,12 @@ function adminrequirement if isdeployed - mymsgbox('This function may require that you are running the software as Administrator (not only be logged in with Administrator rights). To do so right click when starting software and select "Run as administrator".'); -end; + %check if can write file + fid = fopen('delete.me','wt'); + if fid>0 + fclose(fid); + delete('delete.me'); + else + mymsgbox('This function may require that you are running the software as Administrator (not only be logged in with Administrator rights). To do so right click when starting software and select "Run as administrator".'); + end +end diff --git a/source/alignSlides.m b/source/alignSlides.m new file mode 100644 index 0000000..a3c74af --- /dev/null +++ b/source/alignSlides.m @@ -0,0 +1,1268 @@ +function [setnew,r,myoT] = alignSlides(setold,t0, t1, slices, done) +% Registers images from timeframe t0 to t1 in slices s, +%inputs +%int t0 initial timeframe. +%int t1 final timeframe +%index array slices, slices to register, set slices=[] to automaticly detect s where epi and endo is present +% +% done logical(number of timeframes x number of slices) to true to not +% register an image, default is false + +%Written by Daniel +% +%Modified (slightly) for Segment coding standard and debugging by Einar Heiberg. + +global SETNEW OPT_PAR +%parameters + +% faster and less robust parameter example +OPT_PAR.nControl=10; %desired number of control points, range 2-80 increase it to improve results at the cost of running time +OPT_PAR.weigthsRadius=10;% was 5; % raidius around epi and endo to register, in pixels. +OPT_PAR.scale=1; %scales for gaussian low pass filter +OPT_PAR.laplace=10; % smoothing parameter + +%Simulated anealing parameters +OPT_PAR.META.boundTPS=0.1; %parameter bounds +OPT_PAR.META.boundAffine=0.1; +OPT_PAR.META.tMax=1; %maximum time per image in minutes, should not be reached +OPT_PAR.META.TEMP_START=10; %initial temperaure, higher gives more random steps, zero for downhill simplex +OPT_PAR.META.TEMP_END=0; +OPT_PAR.META.MAX_ITER_TOTAL=10; %decrease for faster runtime at the cost of worse results (and increase to improve results) +OPT_PAR.META.MAX_ITER_FIRST=20; +OPT_PAR.META.COOL_RATE=0.95; +OPT_PAR.META.RATIO=.99; +calcResults=false; % get diagnostic results (dice) if true + +% % slower and more robust parameter example +% % +% %parameters +% OPT_PAR.nControl=20; %desired number of control points, range 2-80 increase it to improve results at the cost of running time +% OPT_PAR.weigthsRadius =5; % raidius around epi and endo to register, in pixels. +% OPT_PAR.scale=[1]; %scales for gaussian low pass filter +% OPT_PAR.laplace=10; % smoothing parameter +% +% %Simulated anealing parameters +% OPT_PAR.META.boundTPS=0.1; %parameter bounds +% OPT_PAR.META.boundAffine=0.1; +% OPT_PAR.META.tMax=1; %maximum time per image in minutes, should not be reached +% OPT_PAR.META.TEMP_START=100; %initial temperaure, higher gives more random steps, zero for downhill simplex +% OPT_PAR.META.TEMP_END=0; +% OPT_PAR.META.MAX_ITER_TOTAL=30; %decrease for faster runtime at the cost of worse results (and increase to improve results) +% OPT_PAR.META.MAX_ITER_FIRST=20; +% OPT_PAR.META.COOL_RATE=0.95; +% OPT_PAR.META.RATIO=.99; +% calcResults=false; % get diagnostic results (dice) if true + +SETNEW = setold; +if nargin<5 + done=logical(false(SETNEW.TSize,SETNEW.ZSize)); %default, register all images in range +end + +if nargin<4 + slices=[]; +end + +OPT_PAR.sz = size(SETNEW.IM); + +%Make sure it is a 4 element vector +if length(OPT_PAR.sz)<4 + OPT_PAR.sz = [OPT_PAR.sz 1 1]; + OPT_PAR.sz = OPT_PAR.sz(1:4); +end + +v = ~isnan(SETNEW.EpiX); %true in images where epi is present +if isempty(slices) + slices=find(sum(sum(v,2),1)); %if slice not specified set where endo/epi is availible +end + try + referenceFrame=SETNEW.referenceFrame; %reference frame already specified, ie, we are running again to refine results or add more timeframes + %[OPT_PAR.k,OPT_PAR.z,referenceFrame,slices]=init(referenceFrame,s); %% initilizes weigths and control points + catch + + for i=1:size(slices) + referenceFrame(slices(i))=find(sum(v(:,:,slices(i)),1),1,'first'); + end + %[OPT_PAR.k,OPT_PAR.z,referenceFrame,slices]=init([],s); %% initilizes weigths and control points, sets reference frame if its not specified + end + +r=zeros(OPT_PAR.sz(3),OPT_PAR.sz(4),4); +SETNEW.referenceFrame=referenceFrame; +wbstep = 1/(length(slices)*length(t0:t1)); +wbval = 0; +h = mywaitbarstart(length(slices)*length(t0:t1),dprintf('Generating image stacks')); + for i=1:length(slices) + s=slices(i); + [OPT_PAR.k,OPT_PAR.z]=init(referenceFrame(s),s); + for t=t0:t1 + a=[0 0;eye(2)]; + c=zeros(size(OPT_PAR.z,1),2); + param=[a(:); c(:)]; %initial parameters + + + if ~(done(t,s) || (t==referenceFrame(s))) + tic; + [SETNEW.IM(:,:,t,s),param,r(t,s,1)]=register(SETNEW.IM(:,:,referenceFrame(s),s),SETNEW.IM(:,:,t,s), param,referenceFrame(s),s); + + if calcResults && ~isnan(SETNEW.EpiY(1,t,s)) + + [r(t,s,2:3),myoT(t-t0+1,:,:)]=dice(param,OPT_PAR.z,referenceFrame(s),t,s); + + end + + r(t,s,4)=toc; % time per image + SETNEW.EpiY(:,t,s)=SETNEW.EpiY(:,referenceFrame(s),s); + SETNEW.EpiX(:,t,s)=SETNEW.EpiX(:,referenceFrame(s),s); + SETNEW.EndoY(:,t,s)=SETNEW.EndoY(:,referenceFrame(s),s); + SETNEW.EndoX(:,t,s)=SETNEW.EndoX(:,referenceFrame(s),s); + wbval = wbval + wbstep; +% waitbar(wbval,h); + h = mywaitbarupdate(h); + + end + end + + end + + + + setnew=SETNEW; %return + clear SETNEW + mywaitbarclose(h); +% close(h); + clear OPT_PAR + + + function [dice,myoT,myoR]=dice(param,z,baseframe,t,s,sr) + % dice similarity measure, myocardium overlap coefficient for + % registred and unregistred images, requires endo/epi in t as well as baseframe. + % probably only useful to developer + % not used in registration + global SETNEW OPT_PAR + sz=OPT_PAR.sz; + A=reshape(param(1:6),3,2); + A=[[1 0 0]' A]; + sr=2;%sampling rate + c=reshape(param(7:end),(length(param)-6)/2,2); + EpiR=[SETNEW.EpiY(:,baseframe,s) SETNEW.EpiX(:,baseframe,s)]; + EndoR=[SETNEW.EndoY(:,baseframe,s) SETNEW.EndoX(:,baseframe,s)]; + Epi=[SETNEW.EpiY(:,t,s) SETNEW.EpiX(:,t,s)]; + Endo=[SETNEW.EndoY(:,t,s) SETNEW.EndoX(:,t,s)]; + [X,Y]=meshgrid(1:1:sz(2)*sr,1:1:sz(1)*sr); + myoR=logical(false(sz(1)*sr,sz(2)*sr)); + [IN] = inpolygon(X,Y,EpiR(:,1)*sr,EpiR(:,2)*sr); + myoR(IN)=true; + [IN] = inpolygon(X,Y,EndoR(:,1)*sr,EndoR(:,2)*sr); + myoR(IN)=false; + + myo=logical(false(sz(1)*sr,sz(2)*sr)); + [IN] = inpolygon(X,Y,Epi(:,1)*sr,Epi(:,2)*sr); + myo(IN)=true; + + [IN] = inpolygon(X,Y,Endo(:,1)*sr,Endo(:,2)*sr); + myo(IN)=false; + + myoT=transformIm(myo,A,c,[],z, 'final')>0.5; + dice(1)=2*(sum(myoT(:) .* myoR(:)))/(sum(myoT(:))+sum(myoR(:))); + + dice(2)=2*(sum(myo(:) .* myoR(:)))/(sum(myo(:))+sum(myoR(:))); + + %----------------------------------------------- +function perf= perfusion(t,s) +%----------------------------------------------- +%not used for registration +global SETNEW OPT_PAR +imt=SETNEW.IM(:,:,t,s); + +endopct = (100-20)/100; +epipct = 80/100; + +if endopct < 0 || endopct > 1 || epipct < 0 || epipct > 1 || (1-endopct) > epipct + myfailed('Invalid input of percentage') +end + + + + + %Check if valid segmentation exists + if not(isnan(SETNEW.EndoX(1,t,s)))&¬(isnan(SETNEW.EpiX(1,t,s))) + + %Make sure segmentation is correct + segment('checkconsistency',t,s); + + endox = SETNEW.EndoX(:,t,s); + endoy = SETNEW.EndoY(:,t,s); + epix = SETNEW.EpiX(:,t,s); + epiy = SETNEW.EpiY(:,t,s); + xin = epix+(endox-epix)*(1-endopct); + yin = epiy+(endoy-epiy)*(1-endopct); + xout = epix+(endox-epix)*epipct; + yout = epiy+(endoy-epiy)*epipct; + + end %valid segmentation exist + [X,Y]=meshgrid(1:1:OPT_PAR.sz(1)*1,1:1:OPT_PAR.sz(2)*1); + myoR=logical(false(OPT_PAR.sz(1),OPT_PAR.sz(2))); + [IN] = inpolygon(X,Y,yin,xin); + myoR(IN)=true; + [IN] = inpolygon(X,Y,yout,xout); + myoR(IN)=false; + + + perf(1)=mean(mean(imt(myoR))); + mx=mean(endox); + my=mean(endoy); + mrad=mean(sqrt((endox-mx).^2+(endoy-my).^2)); + theta=1:pi/40:2*pi; + %halvLV=mrad/2*[sin(theta) cos(theta)]; + LV=logical(false(size(myoR))); + LV(inpolygon(X,Y,mrad/2*sin(theta)+my,mrad/2*cos(theta)+mx))=true; + perf(2)=mean(mean(imt(LV))); + + + + + + + + + + + +function curve=transformC(X,A,c,z) + %transforms a curve, + % not used for registration + global OPT_PAR; + + maX=max(max(OPT_PAR.sz(1:2))); + % scale coordinates + X=X./maX-0.5; + K=ctps_gen_K(X,z); + X=[ones(size(X,1),1) X]; + U=X*A+K*[zeros(1,size(c,1))' c]; + U=[U(:,2)./U(:,1) U(:,3)./U(:,1)]; + %descale + curve=(U+0.5).*maX; + +function [k,z,ref,s]=init(ref,s) + %initializes constant parameters before optimization + + global SETNEW OPT_PAR + OPT_PAR.sz=size(SETNEW.IM); + Epi=[SETNEW.EpiY(:,ref,s) SETNEW.EpiX(:,ref,s)]; + Endo=[SETNEW.EndoY(:,ref,s) SETNEW.EndoX(:,ref,s)]; + w = zeros(OPT_PAR.sz(1:2)); + if isempty(SETNEW.EpiX) + %this should never happen, if it did anyway someone probably edited the + %main alignslides function + disp('Warning:No Epi/Endo in slice') + kant=round(0.2*sz(1:2)); + w(kant(1):end-kant(1),kant(2):end-kant(2))=1; + else + %set weigths based on endo/epi + ind=[ [round(SETNEW.EpiX(:,ref,s)) ; round(SETNEW.EndoX(:,ref,s))] [round(SETNEW.EpiY(:,ref,s)); round(SETNEW.EndoY(:,ref,s))]]; + + + OPT_PAR.weightsRadius=5; + for i =1:length(ind) + x=ind(i,1); + y=ind(i,2); + w(min(OPT_PAR.sz(1),max(1,x-OPT_PAR.weightsRadius)):min(OPT_PAR.sz(1),max(1,x+OPT_PAR.weightsRadius)),min(OPT_PAR.sz(2),max(1,y-OPT_PAR.weightsRadius)):min(OPT_PAR.sz(2),max(1,y+OPT_PAR.weightsRadius)))=1; % check if in bounds and set weigths + end + rectanguarGrid=false; + end + + if rectanguarGrid + %rectangular control point grid, not currently used + [col,row] = find(w); + R2=10; + bounds=[min(row)-R2 max(row)+R2;min(col)-R2 max(col)+R2]; + nControl=round(sqrt(OPT_PAR.nControl)); %total number of control points is nControl^2 + gridsize=(bounds(:,2)-bounds(:,1))/nControl; + [X,Y] = meshgrid(gridsize(1)/2:gridsize(1):gridsize(1)*(nControl-0.5),gridsize(1)/2:gridsize(1):gridsize(1)*(nControl-0.5)); + + z=[X(:)+bounds(1,1) Y(:)+bounds(2,1)]; %control points + + else % + % circular control point grid, replace with Helen's code + %%% Use code from Helen (centerline method). + z=Endo/2+Epi/2; + z=z(1:round(length(z)/OPT_PAR.nControl):length(z),:); + %z=[z; mean(z)]; + end +w=w(:); +k=w>0; +[x,y]=meshgrid(1:OPT_PAR.sz(2),1:OPT_PAR.sz(1)); +X=[x(:) y(:)]; +maX=max(max(OPT_PAR.sz(1:2))); +OPT_PAR.X=X(k,:); +OPT_PAR.x=x; +OPT_PAR.y=y; +OPT_PAR.X=(OPT_PAR.X)./maX-0.5; %scale image points +z=z./maX-0.5;%scale control points + + + +function [Ir,param,r] = register(It, Ib, param,t0,s) + + global OPT_PAR; + + META=OPT_PAR.META; + a=[0 0;eye(2)]; + c=zeros(size(OPT_PAR.z,1),2); + param0=[a(:); c(:)]; %initial parameters + + A=eye(3,3); + [~,OPT_PAR.K]=transformIm(It,A,c,[],OPT_PAR.z, 'set_K'); %this will set K + for i =1:length(OPT_PAR.scale) %only one scale currently used + h = fspecial('gaussian',[21 21], OPT_PAR.scale(i)); + IT = imfilter(It , h,'replicate'); + IB = imfilter(Ib, h,'replicate'); + OPT_PAR.IT=reshape(modNGF(IT),OPT_PAR.sz(1:2)); + OPT_PAR.IT=single((OPT_PAR.IT(OPT_PAR.k))); + OPT_PAR.IB=single(reshape(modNGF(IB),OPT_PAR.sz(1:2))); + alfa=META.boundTPS*ones(size(param0)); + alfa(1:6)=META.boundAffine; + ub=param0+alfa; + lb=param0-alfa; + f0=cost_SIMPSA(param0); + options = SIMPSASET('MAX_TIME',1,'TEMP_START',META.TEMP_START,'TEMP_END',0,'MAX_ITER_TOTAL', META.MAX_ITER_TOTAL,'MAX_ITER_TEMP_FIRST', META.MAX_ITER_FIRST,'COOL_RATE',META.COOL_RATE,'TOLFUN',0.001,'DISPLAY','none','TOLX', 10^-3,'INITIAL_ACCEPTANCE_RATIO',META.RATIO); + [param_final,FVAL,EXITFLAG]= SIMPSA('cost_SIMPSA',param0,lb,ub,options);%update parameters for each scale space/pyramid + f1=cost_SIMPSA(param_final); + r=f1/f0; %return for diagnostics + end + param=param_final; %parameters to return + A=reshape(param(1:6),3,2); + A=[[1 0 0]' A]; + c=reshape(param(7:end),(length(param)-6)/2,2); + [Ir]=transformIm(Ib,A,c,[],OPT_PAR.z, 'final'); + + + +function [K] = ctps_gen_K(x,z) + +% calulates TPS kernel matrix +[n, M] = size (x); +[m, N] = size (z); +dim = M; + +% calc. the K matrix. +% 2D: K = r^2 * log r +% 3D: K = -r +K= zeros (n,m); + +for it_dim=1:dim + tmp = x(:,it_dim) * ones(1,m) - ones(n,1) * z(:,it_dim)'; + tmp = tmp .* tmp; + K = K + tmp; + +end +if dim == 2 + mask = K < 1e-10; % to avoid singularity. + K = 0.5*K .* log(K + mask) .* (K>1e-10); +else + K = - sqrt(K); +end + + +function [I1,K,reg,motion_field]=transformIm(I0,A,c,K,z, method) + %image transformation I1=T(I0) + + %inputs + %I0= image to be transformed + %A = affine transformation matrix 3 x 3 + %c = TPS weigths 2 x (number of control points) + %K =TPS kernel (number of control points) x (number of pixels) + %K =[] sets K, do not re-set K if unless pixels or control points + %change + %z = TPS control points + % method = option string + %set_K do not transform, sets K + + % "opt" faster using bilinear interpolation for optimization + % only transforms points w>0 K should already be set + + % "final" whole image transformation + %outputs + % I1 =transformed image + % K =TPS kernel should only be set with "set_K" or "final" + % reg = laplacian regularization only set with "opt" + % motion_field only set by "final" + + + global OPT_PAR + + I1=zeros(size(I0)); + + maX=max(max(OPT_PAR.sz(1:2))); + % scale coordinates + + if isempty(K) + + [K] = ctps_gen_K(OPT_PAR.X,z); + + end + if strcmp('set_K', method) %do nothing, we only want to set K +% + + + elseif strcmp('opt', method) %faster used for optimization + + U= inverseFunc(OPT_PAR.X,A,c,K); + + reg=sum(sum((OPT_PAR.X-U).^2)); + %descale + U=(U+0.5).*maX; + + I1 = interp2(OPT_PAR.x,OPT_PAR.y,I0,U(:,1), U(:,2)); + + elseif strcmp('final', method) % slower, used only for final transformation + [x,y]=meshgrid(1:size(I0,2),1:size(I0,1)); + maX=max(size(I0)); + X=[x(:) y(:)]; + X=X./maX-0.5; + [K] = ctps_gen_K(X,z); + U= inverseFunc(X,A,c,K); + %descale + U=(U+0.5).*maX; + motion_field=(U-X); + I1 = interp2(x,y,I0,U(:,1), U(:,2)); + I1(isnan(I1))=0; + I1=reshape(I1,size(I0)); + end + + + +function U= inverseFunc(X,A,c,K) + %inverse TPS transformation + + X=[ones(size(X,1),1) X]; + U=(X-K*[zeros(1,size(c,1))' c])/(A); + %U=U(:,1:2); + U=[U(:,2)./U(:,1) U(:,3)./U(:,1)]; + %diff=U-U1; + + +function E= cost_SIMPSA(param) + %cost function +global OPT_PAR + J=OPT_PAR.laplace; + A=reshape(param(1:6),3,2); + A=[[1 0 0]' A]; + c=reshape(param(7:end),(length(param)-6)/2,2); + [Itrans,~,reg]= transformIm(OPT_PAR.IB,A,c,OPT_PAR.K,OPT_PAR.z, 'opt'); + E=sum(sum((OPT_PAR.IT-Itrans).^2))+reg*J; + + + + + + + +function G=modNGF(I,noise) + % calculates amplitude of modified normalized gradient field + [FX,FY] = gradient((I)); + + n=numel(I); + gradnorm2=((FX.^2+FY.^2)); + noise_diam=15; + if nargin<2 + noise=noise_est((gradnorm2),ones(noise_diam)); %local noise estimation + %noise=std((gradnorm2(:))); %global noise estimation only for test + end + eps= noise+sum(sum(gradnorm2))/(noise_diam^2); + adjnorm=(gradnorm2+eps.^2).^(1/2); + x=FX./adjnorm; + y=FY./adjnorm; + G=x.^2+y.^2; + +function J = noise_est(varargin) +% modified version of matlabs local noise estimation, classifies edges as +% outliers +%STDFILT Local standard deviation of image. + +% Copyright 1993-2005 The MathWorks, Inc. +% $Revision.2 $ $Date: 2006/06/15 20:09:36 $ + +[I, h] = ParseInputs(varargin{:}); + +if (~isa(I,'double')) + I = double(I); +end + + +n = sum(h(:)); + +% If n = 1 then return default J (all zeros) to avoid the divideByZero warning. +% Otherwise, calculate standard deviation. The formula for standard deviation +% can be rewritten in terms of the theoretical definition of +% convolution. However, in practise, use correlation in IMFILTER to avoid a +% flipped answer when NHOOD is asymmetric. +% conv1 = imfilter(I.^2,h,'symmetric') / (n-1); +% conv2 = imfilter(I,h,'symmetric').^2 / (n*(n-1)); +% std = sqrt(conv1-conv2). +% These equations can be further optimized for speed. +BW = edge(I,'canny'); +%BW=zeros(size(BW)); +n=imfilter(double(~BW), h , 'symmetric'); +n1 = n - 1; +if n ~= 1 + conv1 = imfilter(I.^2, h , 'symmetric')./(n.*n1); + conv2 = imfilter(I, h, 'symmetric').^2 ./ (n.*n1); + J = sqrt(max((conv1 - conv2),0)); +else + J = zeros(size(I)); +end + +%%%%%%%%%%%%%%%ParseInputs%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [I,H] = ParseInputs(varargin) + +narginchk(1,2); + +validateattributes(varargin{1},{'numeric','logical'},{'real','nonsparse'}, ... + mfilename, 'I',1); +I = varargin{1}; + +if nargin == 2 + validateattributes(varargin{2},{'logical','numeric'},{'nonsparse'}, ... + mfilename,'NHOOD',2); + H = varargin{2}; + + eid = sprintf('Images:%s:invalidNeighborhood',mfilename); + + % H must contain zeros and/or ones. + bad_elements = (H ~= 0) & (H ~= 1); + if any(bad_elements(:)) + msg = 'NHOOD must be a matrix that contains zeros and/or ones.'; + error(eid,'%s',msg); + end + + % H's size must be a factor of 2n-1 (odd). + sizeH = size(H); + if any(floor(sizeH/2) == (sizeH/2) ) + msg = 'NHOOD must have a size that is odd in each dimension.'; + error(eid,'%s',msg); + end + + if ~isa(H,'double') + H = double(H); + end + +else + H = ones(3); +end + + + +function [X,FVAL,EXITFLAG,OUTPUT] = SIMPSA(FUN,X0,LB,UB,OPTIONS,varargin) +%SIMPSA finds a minimum of a function of several variables using an algorithm +% that is based on the combination of the non-linear smplex and the simulated +% annealing algorithm (the SIMPSA algorithm, Cardoso et al., 1996). +% In this paper, the algorithm is shown to be adequate for the global optimi- +% zation of an example SETNEW of unconstrained and constrained NLP functions. +% +% SIMPSA attempts to solve problems of the form: +% min F(X) subject to: LB <= X <= UB +% X +% +% Algorithm partly based on section 10.4 and 10.9 in "Numerical Recipes in C", +% ISBN 0-521-43108-5, and the paper of Cardoso et al, 1996. +% +% X=SIMPSA(FUN,X0) start at X0 and finds a minimum X to the function FUN. +% FUN accepts input X and returns a scalar function value F evaluated at X. +% X0 may be a scalar, vector, or matrix. +% +% X=SIMPSA(FUN,X0,LB,UB) defines a SETNEW of lower and upper bounds on the +% design variables, X, so that a solution is found in the range +% LB <= X <= UB. Use empty matrices for LB and UB if no bounds exist. +% SETNEW LB(i) = -Inf if X(i) is unbounded below; SETNEW UB(i) = Inf if X(i) is +% unbounded above. +% +% X=SIMPSA(FUN,X0,LB,UB,OPTIONS) minimizes with the default optimization +% parameters replaced by values in the structure OPTIONS, an argument +% created with the SIMPSASETNEW function. See SIMPSASETNEW for details. +% Used options are TEMP_START, TEMP_END, COOL_RATE, INITIAL_ACCEPTANCE_RATIO, +% MIN_COOLING_FACTOR, MAX_ITER_TEMP_FIRST, MAX_ITER_TEMP_LAST, MAX_ITER_TEMP, +% MAX_ITER_TOTAL, MAX_TIME, MAX_FUN_EVALS, TOLX, TOLFUN, DISPLAY and OUTPUT_FCN. +% Use OPTIONS = [] as a place holder if no options are SETNEW. +% +% X=SIMPSA(FUN,X0,LB,UB,OPTIONS,varargin) is used to supply a variable +% number of input arguments to the objective function FUN. +% +% [X,FVAL]=SIMPSA(FUN,X0,...) returns the value of the objective +% function FUN at the solution X. +% +% [X,FVAL,EXITFLAG]=SIMPSA(FUN,X0,...) returns an EXITFLAG that describes the +% exit condition of SIMPSA. Possible values of EXITFLAG and the corresponding +% exit conditions are: +% +% 1 Change in the objective function value less than the specified tolerance. +% 2 Change in X less than the specified tolerance. +% 0 Maximum number of function evaluations or iterations reached. +% -1 Maximum time exceeded. +% +% [X,FVAL,EXITFLAG,OUTPUT]=SIMPSA(FUN,X0,...) returns a structure OUTPUT with +% the number of iterations taken in OUTPUT.nITERATIONS, the number of function +% evaluations in OUTPUT.nFUN_EVALS, the temperature profile in OUTPUT.TEMPERATURE, +% the simplexes that were evaluated in OUTPUT.SIMPLEX and the best one in +% OUTPUT.SIMPLEX_BEST, the costs associated with each simplex in OUTPUT.COSTS and +% from the best simplex at that iteration in OUTPUT.COST_BEST, the amount of time +% needed in OUTPUT.TIME and the options used in OUTPUT.OPTIONS. +% +% See also SIMPSASETNEW, SIMPSAGET + + + +% Copyright (C) 2006 Brecht Donckels, BIOMATH, brecht.donckels@ugent.be +% +% inspired by: +% Systems Biology Toolbox for MATLAB +% Copyright (C) 2005 Henning Schmidt, FCC, henning@fcc.chalmers.se +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +% USA. + + + +% handle variable input arguments + +if nargin < 5 + OPTIONS = []; + if nargin < 4 + UB = 1e5; + if nargin < 3 + LB = -1e5; + end + end +end + +% check input arguments + +if ~ischar(FUN) + error('''FUN'' incorrectly specified in ''SIMPSA'''); +end +if ~isfloat(X0) + error('''X0'' incorrectly specified in ''SIMPSA'''); +end +if ~isfloat(LB) + error('''LB'' incorrectly specified in ''SIMPSA'''); +end +if ~isfloat(UB) + error('''UB'' incorrectly specified in ''SIMPSA'''); +end +if length(X0) ~= length(LB) + error('''LB'' and ''X0'' have incompatible dimensions in ''SIMPSA'''); +end +if length(X0) ~= length(UB) + error('''UB'' and ''X0'' have incompatible dimensions in ''SIMPSA'''); +end + +% declaration of global variables + +global NDIM nFUN_EVALS TEMP YBEST PBEST + +% SETNEW EXITFLAG to default value + +EXITFLAG = -2; + +% determine number of variables to be optimized + +NDIM = length(X0); + +% seed the random number generator + +rand('state',sum(100*clock)); + +% SETNEW default options + +DEFAULT_OPTIONS = SIMPSASET('TEMP_START',[],... % starting temperature (if none provided, an optimal one will be estimated) + 'TEMP_END',1,... % end temperature + 'COOL_RATE',10,... % small values (<1) means slow convergence,large values (>1) means fast convergence + 'INITIAL_ACCEPTANCE_RATIO',0.95,... % when initial temperature is estimated, this will be the initial acceptance ratio in the first round + 'MIN_COOLING_FACTOR',0.9,... % minimum cooling factor (<1) + 'MAX_ITER_TEMP_FIRST',50,... % number of iterations in the preliminary temperature loop + 'MAX_ITER_TEMP_LAST',50,... % number of iterations in the last temperature loop (pure simplex) + 'MAX_ITER_TEMP',10,... % number of iterations in the remaining temperature loops + 'MAX_ITER_TOTAL',2500,... % maximum number of iterations tout court + 'MAX_TIME',2500,... % maximum duration of optimization + 'MAX_FUN_EVALS',2500,... % maximum number of function evaluations + 'TOLX',1e-6,... % maximum difference between best and worst function evaluation in simplex + 'TOLFUN',1e-3,... % maximum difference between the coordinates of the vertices + 'DISPLAY','none',... % 'iter' or 'none' indicating whether user wants feedback + 'OUTPUT_FCN',[]); % string with output function name + +% update default options with supplied options + +OPTIONS = SIMPSASET(DEFAULT_OPTIONS,OPTIONS); + +% store options in OUTPUT + +OUTPUT.OPTIONS = OPTIONS; + +% initialize simplex +% ------------------ + +% create empty simplex matrix p (location of vertex i in row i) +P = zeros(NDIM+1,NDIM); +% create empty cost vector (cost of vertex i in row i) +Y = zeros(NDIM+1,1); +% SETNEW best vertex of initial simplex equal to initial parameter guess +PBEST = X0(:)'; +% calculate cost with best vertex of initial simplex +YBEST = CALCULATE_COST(FUN,PBEST,LB,UB,varargin{:}); + +% initialize temperature loop +% --------------------------- + +% SETNEW temperature loop number to one +TEMP_LOOP_NUMBER = 1; + +% if no TEMP_START is supplied, the initial temperature is estimated in the first +% loop as described by Cardoso et al., 1996 (recommended) + +% therefore, the temperature is SETNEW to YBEST*1e5 in the first loop +if isempty(OPTIONS.TEMP_START) + TEMP = abs(YBEST)*1e5; +else + TEMP = OPTIONS.TEMP_START; +end + +% initialize OUTPUT structure +% --------------------------- + +OUTPUT.TEMPERATURE = zeros(OPTIONS.MAX_ITER_TOTAL,1); +OUTPUT.SIMPLEX = zeros(NDIM+1,NDIM,OPTIONS.MAX_ITER_TOTAL); +OUTPUT.SIMPLEX_BEST = zeros(OPTIONS.MAX_ITER_TOTAL,NDIM); +OUTPUT.COSTS = zeros(OPTIONS.MAX_ITER_TOTAL,NDIM+1); +OUTPUT.COST_BEST = zeros(OPTIONS.MAX_ITER_TOTAL,1); + +% initialize iteration data +% ------------------------- + +% start timer +tic +% SETNEW number of function evaluations to one +nFUN_EVALS = 1; +% SETNEW number of iterations to zero +nITERATIONS = 0; + +% temperature loop: run SIMPSA till stopping criterion is met +% ----------------------------------------------------------- + +while 1 + + % detect if termination criterium was met + % --------------------------------------- + + % if a termination criterium was met, the value of EXITFLAG should have changed + % from its default value of -2 to -1, 0, 1 or 2 + + if EXITFLAG ~= -2 + break + end + + % SETNEW MAXITERTEMP: maximum number of iterations at current temperature + % -------------------------------------------------------------------- + + if TEMP_LOOP_NUMBER == 1 + MAXITERTEMP = OPTIONS.MAX_ITER_TEMP_FIRST*NDIM; + % The initial temperature is estimated (is requested) as described in + % Cardoso et al. (1996). Therefore, we need to store the number of + % successful and unsuccessful moves, as well as the increase in cost + % for the unsuccessful moves. + if isempty(OPTIONS.TEMP_START) + [SUCCESSFUL_MOVES,UNSUCCESSFUL_MOVES,UNSUCCESSFUL_COSTS] = deal(0); + end + elseif TEMP < OPTIONS.TEMP_END + TEMP = 0; + MAXITERTEMP = OPTIONS.MAX_ITER_TEMP_LAST*NDIM; + else + MAXITERTEMP = OPTIONS.MAX_ITER_TEMP*NDIM; + end + + % construct initial simplex + % ------------------------- + + % 1st vertex of initial simplex + P(1,:) = PBEST; + Y(1) = CALCULATE_COST(FUN,P(1,:),LB,UB,varargin{:}); + + % if output function given then run output function to plot intermediate result + if ~isempty(OPTIONS.OUTPUT_FCN) + feval(OPTIONS.OUTPUT_FCN,P(1,:),Y(1)); + end + + % remaining vertices of simplex + for k = 1:NDIM + % copy first vertex in new vertex + P(k+1,:) = P(1,:); + % alter new vertex + P(k+1,k) = LB(k)+rand*(UB(k)-LB(k)); + % calculate value of objective function at new vertex + Y(k+1) = CALCULATE_COST(FUN,P(k+1,:),LB,UB,varargin{:}); + end + + % store information on what step the algorithm just did + ALGOSTEP = 'initial simplex'; + + % add NDIM+1 to number of function evaluations + nFUN_EVALS = nFUN_EVALS + NDIM; + + % note: + % dimensions of matrix P: (NDIM+1) x NDIM + % dimensions of vector Y: (NDIM+1) x 1 + + % give user feedback if requested + if strcmp(OPTIONS.DISPLAY,'iter') + if nITERATIONS == 0 + disp(' Nr Iter Nr Fun Eval Min function Best function TEMP Algorithm Step'); + else + disp(sprintf('%5.0f %5.0f %12.6g %15.6g %12.6g %s',nITERATIONS,nFUN_EVALS,Y(1),YBEST,TEMP,'best point')); + end + end + + % run full metropolis cycle at current temperature + % ------------------------------------------------ + + % initialize vector COSTS, needed to calculate new temperature using cooling + % schedule as described by Cardoso et al. (1996) + COSTS = zeros((NDIM+1)*MAXITERTEMP,1); + + % initialize ITERTEMP to zero + + ITERTEMP = 0; + + % start + + for ITERTEMP = 1:MAXITERTEMP + + % add one to number of iterations + nITERATIONS = nITERATIONS + 1; + + % Press and Teukolsky (1991) add a positive logarithmic distributed variable, + % proportional to the control temperature T to the function value associated with + % every vertex of the simplex. Likewise,they subtract a similar random variable + % from the function value at every new replacement point. + % Thus, if the replacement point corresponds to a lower cost, this method always + % accepts a true down hill step. If, on the other hand, the replacement point + % corresponds to a higher cost, an uphill move may be accepted, depending on the + % relative COSTS of the perturbed values. + % (taken from Cardoso et al.,1996) + + % add random fluctuations to function values of current vertices + YFLUCT = Y+TEMP*abs(log(rand(NDIM+1,1))); + + % reorder YFLUCT, Y and P so that the first row corresponds to the lowest YFLUCT value + help = sortrows([YFLUCT,Y,P],1); + YFLUCT = help(:,1); + Y = help(:,2); + P = help(:,3:end); + + % store temperature at current iteration + OUTPUT.TEMPERATURE(nITERATIONS) = TEMP; + + % store information about simplex at the current iteration + OUTPUT.SIMPLEX(:,:,nITERATIONS) = P; + OUTPUT.SIMPLEX_BEST(nITERATIONS,:) = PBEST; + + % store cost function value of best vertex in current iteration + OUTPUT.COSTS(nITERATIONS,:) = Y; + OUTPUT.COST_BEST(nITERATIONS) = YBEST; + + if strcmp(OPTIONS.DISPLAY,'iter') + disp(sprintf('%5.0f %5.0f %12.6g %15.6g %12.6g %s',nITERATIONS,nFUN_EVALS,Y(1),YBEST,TEMP,ALGOSTEP)); + end + + % if output function given then run output function to plot intermediate result + if ~isempty(OPTIONS.OUTPUT_FCN) + feval(OPTIONS.OUTPUT_FCN,P(1,:),Y(1)); + end + + % end the optimization if one of the stopping criteria is met + %% 1. difference between best and worst function evaluation in simplex is smaller than TOLFUN + %% 2. maximum difference between the coordinates of the vertices in simplex is less than TOLX + %% 3. no convergence,but maximum number of iterations has been reached + %% 4. no convergence,but maximum time has been reached + + if (abs(max(Y)-min(Y)) < OPTIONS.TOLFUN) && (TEMP_LOOP_NUMBER ~= 1) + if strcmp(OPTIONS.DISPLAY,'iter') + disp('Change in the objective function value less than the specified tolerance (TOLFUN).') + end + EXITFLAG = 1; + break; + end + + if (max(max(abs(P(2:NDIM+1,:)-P(1:NDIM,:)))) < OPTIONS.TOLX) && (TEMP_LOOP_NUMBER ~= 1) + if strcmp(OPTIONS.DISPLAY,'iter') + disp('Change in X less than the specified tolerance (TOLX).') + end + EXITFLAG = 2; + break; + end + + if (nITERATIONS >= OPTIONS.MAX_ITER_TOTAL*NDIM) || (nFUN_EVALS >= OPTIONS.MAX_FUN_EVALS*NDIM*(NDIM+1)) + if strcmp(OPTIONS.DISPLAY,'iter') + disp('Maximum number of function evaluations or iterations reached.'); + end + EXITFLAG = 0; + break; + end + + if toc/60 > OPTIONS.MAX_TIME + if strcmp(OPTIONS.DISPLAY,'iter') + disp('Exceeded maximum time.'); + end + EXITFLAG = -1; + break; + end + + % begin a new iteration + + %% first extrapolate by a factor -1 through the face of the simplex + %% across from the high point,i.e.,reflect the simplex from the high point + [YFTRY,YTRY,PTRY] = AMOTRY(FUN,P,-1,LB,UB,varargin{:}); + + %% check the result + if YFTRY <= YFLUCT(1) + %% gives a result better than the best point,so try an additional + %% extrapolation by a factor 2 + [YFTRYEXP,YTRYEXP,PTRYEXP] = AMOTRY(FUN,P,-2,LB,UB,varargin{:}); + if YFTRYEXP < YFTRY + P(end,:) = PTRYEXP; + Y(end) = YTRYEXP; + ALGOSTEP = 'reflection and expansion'; + else + P(end,:) = PTRY; + Y(end) = YTRY; + ALGOSTEP = 'reflection'; + end + elseif YFTRY >= YFLUCT(NDIM) + %% the reflected point is worse than the second-highest, so look + %% for an intermediate lower point, i.e., do a one-dimensional + %% contraction + [YFTRYCONTR,YTRYCONTR,PTRYCONTR] = AMOTRY(FUN,P,-0.5,LB,UB,varargin{:}); + if YFTRYCONTR < YFLUCT(end) + P(end,:) = PTRYCONTR; + Y(end) = YTRYCONTR; + ALGOSTEP = 'one dimensional contraction'; + else + %% can't seem to get rid of that high point, so better contract + %% around the lowest (best) point + X = ones(NDIM,NDIM)*diag(P(1,:)); + P(2:end,:) = 0.5*(P(2:end,:)+X); + for k=2:NDIM + Y(k) = CALCULATE_COST(FUN,P(k,:),LB,UB,varargin{:}); + end + ALGOSTEP = 'multiple contraction'; + end + else + %% if YTRY better than second-highest point, use this point + P(end,:) = PTRY; + Y(end) = YTRY; + ALGOSTEP = 'reflection'; + end + + % the initial temperature is estimated in the first loop from + % the number of successfull and unsuccesfull moves, and the average + % increase in cost associated with the unsuccessful moves + + if TEMP_LOOP_NUMBER == 1 && isempty(OPTIONS.TEMP_START) + if Y(1) > Y(end) + SUCCESSFUL_MOVES = SUCCESSFUL_MOVES+1; + elseif Y(1) <= Y(end) + UNSUCCESSFUL_MOVES = UNSUCCESSFUL_MOVES+1; + UNSUCCESSFUL_COSTS = UNSUCCESSFUL_COSTS+(Y(end)-Y(1)); + end + end + + end + + % stop if previous for loop was broken due to some stop criterion + if ITERTEMP < MAXITERTEMP + break; + end + + % store cost function values in COSTS vector + COSTS((ITERTEMP-1)*NDIM+1:ITERTEMP*NDIM+1) = Y; + + % calculated initial temperature or recalculate temperature + % using cooling schedule as proposed by Cardoso et al. (1996) + % ----------------------------------------------------------- + + if TEMP_LOOP_NUMBER == 1 && isempty(OPTIONS.TEMP_START) + TEMP = -(UNSUCCESSFUL_COSTS/(SUCCESSFUL_MOVES+UNSUCCESSFUL_MOVES))/log(((SUCCESSFUL_MOVES+UNSUCCESSFUL_MOVES)*OPTIONS.INITIAL_ACCEPTANCE_RATIO-SUCCESSFUL_MOVES)/UNSUCCESSFUL_MOVES); + elseif TEMP_LOOP_NUMBER ~= 0 + STDEV_Y = std(COSTS); + COOLING_FACTOR = 1/(1+TEMP*log(1+OPTIONS.COOL_RATE)/(3*STDEV_Y)); + TEMP = TEMP*min(OPTIONS.MIN_COOLING_FACTOR,COOLING_FACTOR); + end + + % add one to temperature loop number + TEMP_LOOP_NUMBER = TEMP_LOOP_NUMBER+1; + +end + +% return solution +X = PBEST; +FVAL = YBEST; + +% store number of function evaluations +OUTPUT.nFUN_EVALS = nFUN_EVALS; + +% store number of iterations +OUTPUT.nITERATIONS = nITERATIONS; + +% trim OUTPUT data structure +OUTPUT.TEMPERATURE(nITERATIONS+1:end) = []; +OUTPUT.SIMPLEX(:,:,nITERATIONS+1:end) = []; +OUTPUT.SIMPLEX_BEST(nITERATIONS+1:end,:) = []; +OUTPUT.COSTS(nITERATIONS+1:end,:) = []; +OUTPUT.COST_BEST(nITERATIONS+1:end) = []; + +% store the amount of time needed in OUTPUT data structure +OUTPUT.TIME = toc; + +return + +% ============================================================================== + +% AMOTRY FUNCTION +% --------------- + +function [YFTRY,YTRY,PTRY] = AMOTRY(FUN,P,fac,LB,UB,varargin) +% Extrapolates by a factor fac through the face of the simplex across from +% the high point, tries it, and replaces the high point if the new point is +% better. + +global NDIM TEMP + +% calculate coordinates of new vertex +psum = sum(P(1:NDIM,:))/NDIM; +PTRY = psum*(1-fac)+P(end,:)*fac; + +% evaluate the function at the trial point. +YTRY = CALCULATE_COST(FUN,PTRY,LB,UB,varargin{:}); +% substract random fluctuations to function values of current vertices +YFTRY = YTRY-TEMP*abs(log(rand(1))); + +return + +% ============================================================================== + +% COST FUNCTION EVALUATION +% ------------------------ + +function [YTRY] = CALCULATE_COST(FUN,PTRY,LB,UB,varargin) + +global YBEST PBEST NDIM nFUN_EVALS + +for i = 1:NDIM + % check lower bounds + if PTRY(i) < LB(i) + YTRY = 1e12+(LB(i)-PTRY(i))*1e6; + return + end + % check upper bounds + if PTRY(i) > UB(i) + YTRY = 1e12+(PTRY(i)-UB(i))*1e6; + return + end +end + +% calculate cost associated with PTRY +YTRY = feval(FUN,PTRY,varargin{:}); + +% add one to number of function evaluations +nFUN_EVALS = nFUN_EVALS + 1; + +% save the best point ever +if YTRY < YBEST + YBEST = YTRY; + PBEST = PTRY; +end + +return + +function options = SIMPSASET(varargin) +%SIMPSASETNEW Create/alter simpsa optimization OPTIONS structure. +% OPTIONS = SIMPSASETNEW('PARAM1',VALUE1,'PARAM2',VALUE2,...) creates an +% optimization options structure OPTIONS in which the named parameters have +% the specified values. Any unspecified parameters are SETNEW to [] (parameters +% with value [] indicate to use the default value for that parameter when +% OPTIONS is passed to the optimization function). It is sufficient to type +% only the leading characters that uniquely identify the parameter. Case is +% ignored for parameter names. +% NOTE: For values that are strings, the complete string is required. +% +% OPTIONS = SIMPSASETNEW(OLDOPTS,'PARAM1',VALUE1,...) creates a copy of OLDOPTS +% with the named parameters altered with the specified values. +% +% OPTIONS = SIMPSASETNEW(OLDOPTS,NEWOPTS) combines an existing options structure +% OLDOPTS with a new options structure NEWOPTS. Any parameters in NEWOPTS +% with non-empty values overwrite the corresponding old parameters in +% OLDOPTS. +% +% SIMPSASETNEW with no input arguments and no output arguments displays all +% parameter names and their possible values, with defaults shown in {} +% when the default is the same for all functions that use that option -- use +% SIMPSASETNEW(OPTIMFUNCTION) to see options for a specific function. +% +% OPTIONS = SIMPSASETNEW (with no input arguments) creates an options structure +% OPTIONS where all the fields are SETNEW to []. + +% See also SIMPSAGET, SIMPSA +% +% Copyright (C) 2006 Brecht Donckels, BIOMATH, brecht.donckels@ugent.be +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +% USA. + + + +% Print out possible values of properties. +if (nargin == 0) && (nargout == 0) + fprintf(' TEMP_START: [ positive scalar ]\n'); + fprintf(' TEMP_END: [ positive scalar ]\n'); + fprintf(' COOL_RATE: [ positive scalar ]\n'); + fprintf(' INITIAL_ACCEPTANCE_RATIO: [ positive scalar < 1 {0.95} ]\n'); + fprintf(' MIN_COOLING_FACTOR: [ positive scalar < 1 {0.9}]\n'); + fprintf(' MAX_ITER_TEMP_FIRST: [ positive scalar {100} ]\n'); + fprintf(' MAX_ITER_TEMP_LAST: [ positive scalar {20} ]\n'); + fprintf(' MAX_ITER_TOTAL: [ positive scalar {2500} ]\n'); + fprintf(' MAX_TIME: [ positive scalar {2500} ]\n'); + fprintf(' MAX_FUN_EVALS: [ positive scalar {2500} ]\n'); + fprintf(' TOLX: [ positive scalar {1e-6} ]\n'); + fprintf(' TOLFUN: [ positive scalar {1e-6} ]\n'); + fprintf(' DISPLAY: [ ''iter'' or ''none'' {''iter''} ]\n'); + fprintf(' OUTPUT_FCN: [ function_handle ]\n'); + fprintf('\n'); +return; +end + +Names = [ + 'TEMP_START ' + 'TEMP_END ' + 'COOL_RATE ' + 'INITIAL_ACCEPTANCE_RATIO ' + 'MIN_COOLING_FACTOR ' + 'MAX_ITER_TEMP_FIRST ' + 'MAX_ITER_TEMP_LAST ' + 'MAX_ITER_TEMP ' + 'MAX_ITER_TOTAL ' + 'MAX_TIME ' + 'MAX_FUN_EVALS ' + 'TOLX ' + 'TOLFUN ' + 'DISPLAY ' + 'OUTPUT_FCN ' + ]; + +m = size(Names,1); +names = lower(Names); + +% Combine all leading options structures o1, o2, ... in odeSETNEW(o1,o2,...). +options = []; +for j = 1:m + options.(deblank(Names(j,:))) = []; +end +i = 1; +while i <= nargin + arg = varargin{i}; + if ischar(arg) % arg is an option name + break; + end + if ~isempty(arg) % [] is a valid options argument + if ~isa(arg,'struct') + error('MATLAB:odeSETNEW:NoPropNameOrStruct',... + ['Expected argument %d to be a string property name ' ... + 'or an options structure\ncreated with SIMANSETNEW.'], i); + end + for j = 1:m + if any(strcmp(fieldnames(arg),deblank(Names(j,:)))) + val = arg.(deblank(Names(j,:))); + else + val = []; + end + if ~isempty(val) + options.(deblank(Names(j,:))) = val; + end + end + end + i = i + 1; +end + +% A finite state machine to parse name-value pairs. +if rem(nargin-i+1,2) ~= 0 + error('MATLAB:odeSETNEW:ArgNameValueMismatch',... + 'Arguments must occur in name-value pairs.'); +end +expectval = 0; % start expecting a name, not a value +while i <= nargin + arg = varargin{i}; + + if ~expectval + if ~ischar(arg) + error('MATLAB:odeSETNEW:NoPropName',... + 'Expected argument %d to be a string property name.', i); + end + + lowArg = lower(arg); + j = strmatch(lowArg,names); + if isempty(j) % if no matches + error('MATLAB:odeSETNEW:InvalidPropName',... + 'Unrecognized property name ''%s''.', arg); + elseif length(j) > 1 % if more than one match + % Check for any exact matches (in case any names are subSETNEWs of others) + k = strmatch(lowArg,names,'exact'); + if length(k) == 1 + j = k; + else + msg = sprintf('Ambiguous property name ''%s'' ', arg); + msg = [msg '(' deblank(Names(j(1),:))]; + for k = j(2:length(j))' + msg = [msg ', ' deblank(Names(k,:))]; + end + msg = sprintf('%s).', msg); + error('MATLAB:odeSETNEW:AmbiguousPropName', msg); + end + end + expectval = 1; % we expect a value next + + else + options.(deblank(Names(j,:))) = arg; + expectval = 0; + + end + i = i + 1; +end + +if expectval + error('MATLAB:odeSETNEW:NoValueForProp',... + 'Expected value for property ''%s''.', arg); +end + + + + \ No newline at end of file diff --git a/source/annotationpoint.m b/source/annotationpoint.m index 1257b6a..7b47b9d 100644 --- a/source/annotationpoint.m +++ b/source/annotationpoint.m @@ -12,98 +12,6 @@ feval(varargin{:}); % FEVAL switchyard end -%--------------------------------- -function pointmove_Callback(dx,dy) %#ok -%--------------------------------- -%Helper function to move points. -global SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -pos = pointfind(true); %Call it in silent mode - -if isnan(pos) - return; -end; - -tools('enableundo',no); - -SET(no).Point.X(pos) = SET(no).Point.X(pos)+dx; -SET(no).Point.Y(pos) = SET(no).Point.Y(pos)+dy; - -drawfunctions('drawsliceno'); - -%----------------------------- -function pointforward_Callback %#ok -%----------------------------- -%Track point forward in time. -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -pos = pointfind; - -if isnan(SET(no).Point.T(pos)) - myfailed('Not a time-resolved point.',DATA.GUI.Segment); - return; -end; - -x = SET(no).Point.X(pos); -y = SET(no).Point.Y(pos); -z = SET(no).Point.Z(pos); -label = SET(no).Point.Label{pos}; - -%Find corresponding point -t = SET(no).CurrentTimeFrame; -t = t+1; -if t>SET(no).TSize - t = 1; -end; - -%Possible matches -ind = find((round(SET(no).Point.Z)==z)&(SET(no).Point.T==t)); -score = 1e10; %Smaller the better -foundind = NaN; -for loop=1:length(ind) - if isequal(SET(no).Point.Label{ind(loop)},label) - temp = sqrt(... - (SET(no).Point.X(ind(loop))-x).^2+... - (SET(no).Point.Y(ind(loop))-y).^2); - if temp0 @@ -186,7 +107,7 @@ function pointclearall_helper(no) outdata{4+offset,1} = 'Time[ms]'; for tloop=1:SET(no).TSize outdata{4+offset+tloop,1} = (tloop-1)*SET(no).TIncr*1000; - end; + end %extract data ind = not(isnan(SET(no).Point.T)); @@ -200,55 +121,25 @@ function pointclearall_helper(no) outdata{4+offset,3+(loop-1)*4} = 'X'; outdata{4+offset,4+(loop-1)*4} = 'Y'; outdata{4+offset,5+(loop-1)*4} = 'Z'; - end; + end for lloop=1:length(labelstodo) for loop=1:length(SET(no).Point.X) if not(isnan(SET(no).Point.T(loop)))&&isequal(labelstodo{lloop},SET(no).Point.Label{loop}) if not(isempty(outdata{4+offset+SET(no).Point.T(loop),2+(lloop-1)*4})) - mywarning(dprintf(... - 'Multiple points with same label, ambigous result. Timeframe %d, slice %d ',... + mywarning(dprintf('Multiple points with same label, ambigous result. Timeframe %d, slice %d ',... SET(no).Point.T(loop),SET(no).Point.Z(loop)),DATA.GUI.Segment); - end; + end outdata{4+offset+SET(no).Point.T(loop),2+(lloop-1)*4} = SET(no).Point.Label{loop}; outdata{4+offset+SET(no).Point.T(loop),3+(lloop-1)*4} = SET(no).Point.X(loop)*SET(no).ResolutionX; outdata{4+offset+SET(no).Point.T(loop),4+(lloop-1)*4} = SET(no).Point.Y(loop)*SET(no).ResolutionY; outdata{4+offset+SET(no).Point.T(loop),5+(lloop-1)*4} = SET(no).Point.Z(loop)*(SET(no).SliceThickness+SET(no).SliceGap); - end; - end; - end; -end; - -segment('cell2clipboard',outdata); - -%------------------------------- -function pointdeletethis_Callback %#ok -%------------------------------- -%Delete point - -global SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; -tools('enableundo',no); - -pos = pointfind; -if isnan(pos) - myfailed('No point found.'); - return; + end + end + end end -ind = true(1,length(SET(no).Point.X)); -ind(pos) = false; -SET(no).Point.X = SET(no).Point.X(ind); -SET(no).Point.Y = SET(no).Point.Y(ind); -SET(no).Point.T = SET(no).Point.T(ind); -SET(no).Point.Z = SET(no).Point.Z(ind); -SET(no).Point.Label = SET(no).Point.Label(ind); -drawfunctions('drawimageno'); +segment('cell2clipboard',outdata); %------------------------------------ function pointcleartemplate_Callback %#ok @@ -260,20 +151,20 @@ function pointclearall_helper(no) no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; -end; +end if isempty(SET(no).Point)||isempty(SET(no).Point.X) myfailed('No points to delete.',DATA.GUI.Segment) return; -end; +end -s = inputdlg({'Delete points labeled as:'},'Template',1,{''}); +s = myinputdlg({'Delete points labeled as:'},'Template',1,{''}); if isempty(s) myfailed('Invalid template.',DATA.GUI.Segment); return; else s = s{1}; -end; +end tools('enableundo',no); @@ -281,72 +172,19 @@ function pointclearall_helper(no) for loop=1:length(SET(no).Point.Z) if isequal(SET(no).Point.Label{loop},s) ind(loop) = false; - end; -end; + end +end -if ~yesno(dprintf('Deleting %d points are you sure?',sum(not(ind))),[],DATA.GUI.Segment); +if ~yesno(dprintf('Deleting %d points are you sure?',sum(not(ind))),[],DATA.GUI.Segment) return; -end; - -SET(no).Point.X = SET(no).Point.X(ind); -SET(no).Point.Y = SET(no).Point.Y(ind); -SET(no).Point.T = SET(no).Point.T(ind); -SET(no).Point.Z = SET(no).Point.Z(ind); -SET(no).Point.Label = SET(no).Point.Label(ind); -drawfunctions('drawimageno'); - -%------------------------------------------ -function pointmaketimeresolvedthis_Callback %#ok -%------------------------------------------ -%Converts a none time resolved point to a time resolved point. -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; -tools('enableundo',no); - -pos = pointfind; - -if isnan(pos) - myfailed('No point found'); - return; end -ind = true(1,length(SET(no).Point.X)); -ind(pos) = false; - -%Backup -x = SET(no).Point.X(pos); -y = SET(no).Point.Y(pos); -z = SET(no).Point.Z(pos); -label = SET(no).Point.Label(pos); - -%Remove old SET(no).Point.X = SET(no).Point.X(ind); SET(no).Point.Y = SET(no).Point.Y(ind); SET(no).Point.T = SET(no).Point.T(ind); SET(no).Point.Z = SET(no).Point.Z(ind); SET(no).Point.Label = SET(no).Point.Label(ind); - -%Add new -x = repmat(x,[1 SET(no).TSize]); -y = repmat(y,[1 SET(no).TSize]); -z = repmat(z,[1 SET(no).TSize]); -t = 1:SET(no).TSize; -label = repmat(label,[1 SET(no).TSize]); -SET(no).Point.X = cat(2,SET(no).Point.X,x); -SET(no).Point.Y = cat(2,SET(no).Point.Y,y); -SET(no).Point.Z = cat(2,SET(no).Point.Z,z); -SET(no).Point.T = cat(2,SET(no).Point.T,t); -SET(no).Point.Label = cat(2,SET(no).Point.Label,label); - -mymsgbox('Point now timeresolved.','Done!',DATA.GUI.Segment); - -%Update image -drawfunctions('drawimageno'); +viewfunctions('setview'); %drawfunctions('drawimageno'); %------------------------------------ function pointrenametemplate_Callback %#ok @@ -358,237 +196,39 @@ function pointclearall_helper(no) no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; -end; +end if isempty(SET(no).Point)||isempty(SET(no).Point.X) pointclearall; myfailed('No points exist.',DATA.GUI.Segment); return; -end; +end -s = inputdlg({'Rename points labeled as:'},'Template',1,{''}); +s = myinputdlg({'Rename points labeled as:'},'Template',1,{''}); if isempty(s) myfailed('Invalid template.',DATA.GUI.Segment); return; else s = s{1}; -end; +end -stri = inputdlg({'New name:'},'Newname',1,{''}); +stri = myinputdlg({'New name:'},'Newname',1,{''}); if isempty(stri) myfailed('Invalid new name.',DATA.GUI.Segment); return; else stri = stri{1}; -end; +end tools('enableundo',no); for loop=1:length(SET(no).Point.Z) if isequal(SET(no).Point.Label{loop},s) SET(no).Point.Label{loop} = stri; - end; -end; - -drawfunctions('drawimageno'); - -%-------------------------------- -function pointrenamethis_Callback %#ok -%-------------------------------- -%Rename point -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; -tools('enableundo',no); - -ind = pointfind; - -if isnan(ind) - myfailed('No point found.'); - return; -end - -s = inputdlg({'Enter name'},'Name',1,{sprintf('%s',SET(no).Point.Label{ind})}); -if isempty(s) - myfailed('Invalid name.',DATA.GUI.Segment); - return; -end; -SET(no).Point.Label(ind) = s; - -drawfunctions('drawimageno'); - -%------------------------------ -function pointclearall_Callback %#ok -%------------------------------ -%Clear all points. -global SET NO DATA - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; -tools('enableundo',no); - -pointclearall_helper(no); - -if strcmp(DATA.CurrentTheme,'3dp') - segment3dp.tools('update3DP') -else - drawfunctions('drawimageno'); -end -%---------------------- -function point_Buttonup %#ok -%---------------------- -%Button up function for points. -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; -tools('enableundo',no); - -%Restore so no motion is called -set(DATA.imagefig,'WindowButtonMotionFcn',''); - -%Restore main buttonup function -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - -SET(no).Point.X(DATA.MeasureN) = DATA.MeasureX; -SET(no).Point.Y(DATA.MeasureN) = DATA.MeasureY; - -drawfunctions('drawimageno'); - - - -%-------------------- -function point_Motion %#ok -%-------------------- -%Motion function for points. -global DATA SET NO - -%If straintagging initiated adjust LVupdated -if ~isempty(SET(NO).StrainTagging) && isfield(SET(NO).StrainTagging, 'LVupdated') - SET(NO).StrainTagging.LVupdated = 1; -end - -[x,y,slice] = segment('getclickedcoords'); - -% first line is for montage -% second line is for one-view. -if (slice==SET(NO).CurrentSlice) && ... - (x>0.5) && (y>0.5) && (x -%------------------------------- -%Find neareast point. -global DATA SET NO - -%Get clicked coordinate -[x,y,slice] = segment('getclickedcoords'); - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -%Find correct point -ind = NaN; -mindist = 1e10; -for loop=1:length(SET(no).Point.X) - if slice==round(SET(no).Point.Z(loop)) - if (isnan(SET(no).Point.T(loop))) || (SET(no).Point.T(loop)==SET(no).CurrentTimeFrame) - dist = min(sqrt(... - (SET(no).Point.X(loop)-y).^2+... - (SET(no).Point.Y(loop)-x).^2)); - if dist -%-------------------------------------- -%Buttondown function when clicked at a point. -global DATA SET NO - -if nargin==1 - type = get(DATA.imagefig,'SelectionType'); -end; - -segment('switchtopanel',panel); - -[~,~,slice] = segment('getclickedcoords'); -if (slice>SET(NO).ZSize) - return; + end end -segment('switchtoslice',slice); - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -ind = pointfind; - -%Prepare DATA.Measure info -DATA.MeasureN = ind; -DATA.MeasureX = SET(no).Point.X(ind); -DATA.MeasureY = SET(no).Point.Y(ind); -switch DATA.ViewPanelsType{panel} - case {'one','mmodespatial','ortho'} - DATA.MeasureOffsetX = 0; - DATA.MeasureOffsetY = 0; - case {'montage','montagerow','montagefit','sax3'} - DATA.MeasureOffsetY = SET(no).XSize*floor((slice-1)/DATA.ViewPanelsMatrix{panel}(2)); - DATA.MeasureOffsetX = SET(no).YSize*mod(slice-1,DATA.ViewPanelsMatrix{panel}(2)); - otherwise - return; -end; - -switch type - case 'alt' - DATA.contextmenu; - otherwise - %Call point motion - set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''point_Motion'');',mfilename)); - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''point_Buttonup'')',mfilename)); -end; +viewfunctions('setview'); %drawfunctions('drawimageno'); %---------------------------- function filterpoints_Callback %#ok @@ -602,15 +242,14 @@ function pointat_Buttondown(panel,type) %#ok no = NO; %Find points to filter -z = SET(no).Point.Z; labels = SET(no).Point.Label; labels = union(labels,{}); %Remove duplicates. c = mymenu('Select point to filter',labels{:}); if isequal(c,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end name = labels{c}; %This is the name to be found. @@ -621,8 +260,8 @@ function pointat_Buttondown(panel,type) %#ok for loop = 1:length(SET(no).Point.X) if isequal(SET(no).Point.Label{loop},name) ind(loop) = true; - end; -end; + end +end %Extract x = SET(no).Point.X; @@ -634,7 +273,7 @@ function pointat_Buttondown(panel,type) %#ok if ~isequal(length(x),SET(no).TSize) myfailed('Number of points is not equal to number of timeframes. Duplicated point names?'); return; -end; +end %Ask for standard deviation s.Noise = 0.3; @@ -642,7 +281,7 @@ function pointat_Buttondown(panel,type) %#ok if ~ok myfailed('Aborted or illegal value.'); return; -end; +end %Extract it objectnoise = s.Noise; @@ -662,9 +301,9 @@ function pointat_Buttondown(panel,type) %#ok hold on; plot(t,xnew,'b-'); hold off; -title('X-coordinate.'); -xlabel('Time [s]'); -ylabel('Position (pixel)'); +title(dprintf('X-coordinate.')); +xlabel(dprintf('Time [s]')); +ylabel(dprintf('Position (pixel)')); %X coordinate subplot(2,1,2); @@ -672,17 +311,17 @@ function pointat_Buttondown(panel,type) %#ok hold on; plot(t,ynew,'b-'); hold off; -title('Y-coordinate.'); -xlabel('Time [s]'); -ylabel('Position (pixel)'); +title(dprintf('Y-coordinate.')); +xlabel(dprintf('Time [s]')); +ylabel(dprintf('Position (pixel)')); -set(99,'numbertitle','off','name','Position over time'); +set(99,'numbertitle','off','name',dprintf('Position over time')); %Crop it back from triplicate xnew = xnew((length(x)+1):2*length(x)); ynew = ynew((length(y)+1):2*length(y)); -if yesno('Do you want to apply filter?'); +if yesno('Do you want to apply filter?') %Prepare to store by backup... tools('enableundo',no); @@ -691,11 +330,10 @@ function pointat_Buttondown(panel,type) %#ok SET(no).Point.Y(ind) = ynew; mymsgbox('Filter applied.'); -end; +end close(99); - %---------------------------------------------- function importpoint_Callback(no) %#ok %---------------------------------------------- @@ -710,7 +348,7 @@ function importpoint_Callback(no) %#ok if length(SET)<2 myfailed('Only one image stack in memory, import from file instead (under File menu).',DATA.GUI.Segment); return; -end; +end if nargin==0 %Find what imagestack @@ -726,17 +364,17 @@ function importpoint_Callback(no) %#ok return; else no = impstacks(s); - end; -end; + end +end if no==NO myfailed('Cannot import from same image stack.',DATA.GUI.Segment); return; -end; +end if (no>length(SET))||(no<1) myfailed('Invalid image stack selected.',DATA.GUI.Segment); return; -end; +end %Check what to do - later optionally take from input arguments. if ~isempty(SET(no).Point) @@ -745,11 +383,8 @@ function importpoint_Callback(no) %#ok return; end - -segment('updatemodeldisplay'); segment('updatevolume'); -segment_main('viewrefreshall_Callback'); -drawfunctions('drawallslices'); +viewfunctions('setview'); %---------------------------------------------------------------------------------- function importpointhelper(tono,fromno) @@ -757,59 +392,32 @@ function importpointhelper(tono,fromno) %Helper function to segmentimportsegmention Callback. %- tono is destination of segmentation. %- fromno is source. -% -%The function is capable of handeling slice offsets and different -%pixelssizes as well as situations when number of timeframes differ. When -%destination is not timeresolved and source is timeresolved then user is -%asked from what timeframe to take the segmentation from. -% -%Work horse in importing. This function would benefit from anti-cut -%and paste treatment. global SET -[sourceslices,destslices,sourcetime,desttime,zdirsource,zdirdest] = ... - segmentation('findmatchingslices',tono,fromno,0,0,0,0); - -%Loop over the number of slices in destination images -if ~isempty(SET(tono).Point) - currentind = length(SET(tono).Point.X); -else - currentind = 0; -end -for zloop = 1:length(destslices) - - %Match slices, see above. - sourceslice = sourceslices(zloop); - destslice = destslices(zloop); - - %Match positions - cornerpossource = SET(fromno).ImagePosition-zdirsource*(zloop-1)*(SET(fromno).SliceThickness+SET(fromno).SliceGap); - cornerposdest = SET(tono).ImagePosition-zdirdest*(destslice-1)*(SET(tono).SliceThickness+SET(tono).SliceGap); - - xofs = (cornerpossource-cornerposdest)*(SET(tono).ImageOrientation(4:6)'); %Project on one axis in mm - yofs = (cornerpossource-cornerposdest)*(SET(tono).ImageOrientation(1:3)'); %Project on the other axis in mm - - xofs = xofs / SET(tono).ResolutionX; %Now in pixels in destination coordinates - yofs = yofs / SET(tono).ResolutionY; %Now in pixels in destination coordinates +x = SET(fromno).Point.X; +y = SET(fromno).Point.Y; +z = SET(fromno).Point.Z; - %factor between - fx = SET(fromno).ResolutionX/SET(tono).ResolutionX; - fy = SET(fromno).ResolutionY/SET(tono).ResolutionY; - - ind = find(SET(fromno).Point.Z == sourceslice); - if ~isempty(ind) - %Equal time resolution - if isequal(desttime,sourcetime) - SET(tono).Point.X(currentind+1:currentind+length(ind)) = min(SET(tono).XSize,max(1,SET(fromno).Point.X(ind)*fx+xofs)); - SET(tono).Point.Y(currentind+1:currentind+length(ind)) = min(SET(tono).YSize,max(1,SET(fromno).Point.Y(ind)*fy+yofs)); - SET(tono).Point.T(currentind+1:currentind+length(ind)) = SET(fromno).Point.T(ind); - SET(tono).Point.Z(currentind+1:currentind+length(ind)) = ones(1,length(ind))*destslice; - for indloop = 1:length(ind) - SET(tono).Point.Label{currentind+indloop} = SET(fromno).Point.Label{ind(indloop)}; - end - currentind = currentind+length(ind); - end +%Convert coordinates +pos = calcfunctions('xyz2rlapfh',fromno,x,y,z); +pos = calcfunctions('rlapfh2xyz',tono,pos(:,1),pos(:,2),pos(:,3)); + +%Copy the points +for loop = 1:size(pos,2) + x = pos(1,loop); + y = pos(2,loop); + z = pos(3,loop); + if ... + (x>0) && (x<=SET(tono).XSize) && ... + (y>0) && (y<=SET(tono).YSize) && ... + (z>0) && (z<=SET(tono).ZSize) + SET(tono).Point.X(end+1) = x; + SET(tono).Point.Y(end+1) = y; + SET(tono).Point.Z(end+1) = z; + SET(tono).Point.T(end+1) = SET(fromno).Point.T(loop); + SET(tono).Point.Label{end+1} = SET(fromno).Point.Label{loop}; end - -end; + +end + diff --git a/source/anonymization.m b/source/anonymization.m new file mode 100644 index 0000000..470327b --- /dev/null +++ b/source/anonymization.m @@ -0,0 +1,704 @@ + function varargout = anonymization(varargin) +%--------------------------------------------- +% ANONYMIZATION GUI for pseudonymization of dicom-files or mat-files as +%extensive, partial or corrective pseudonymization, for a single file/folder or for +%a whole working list. + +% Written by Jane Tufvesson + +%Todo +% :code to make partial/normal anonymization of dicom files +% +% : code to make full anonymization of dicom files +% +% : code to make corrective anonymization of dicom files by removing +% the added tags +% +% :rewrite find patient details to be compatible with import to work +% list + +macro_helper(varargin{:}); +[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard + +%----------------------------- +function initgui(filetype) +%----------------------------- +global SET DATA WL + +if ~isempty(SET) + myfailed('Please save and close your current analysis in order to pseudonymize multiple files.'); + return +end + +%open figure +if isequal(filetype,'mat') + DATA.GUI.Anonymization = mygui('anonymizationmat.fig'); + WL=[]; +elseif isequal(filetype,'dcm') + DATA.GUI.Anonymization = mygui('anonymizationdicom.fig'); + WL=[]; +end +fig = DATA.GUI.Anonymization.fig; + +set(fig,'DeleteFcn','anonymization(''deletegui_Callback'')'); + +updatelist; + +%-------------------------- +function deletegui_Callback +%-------------------------- +global DATA WL + +try + DATA.GUI.Anonymization = close(DATA.GUI.Anonymization); +catch %#ok + delete(gcf); + if isa(DATA,'maingui') + DATA.GUI.Anonymization = []; + end +end + +WL=[]; + +%-------------------------- +function updategui_Callback +%-------------------------- +updatelist; + +%----------------------------- +function addsinglemat_Callback +%----------------------------- +global DATA + +%select file +[filename{1},filepath{1}] = myuigetfile('*.mat','Select .mat-file.'); +if isequal(filepath{1},0)||isequal(filename,0) + myfailed('Function aborted. No file selected.',DATA.GUI.Segment); + return; +end + +[~,filename{1}] = fileparts(filename{1}); + +%add to worklist +addtolistmat(filepath,filename); + +%----------------------------- +function addmatfolder_Callback +%----------------------------- +global DATA + +%select folder +pathname = DATA.Pref.datapath; +pathname = myuigetdir(pathname,'Select a folder (including subfolders) with .mat files'); + +if isequal(pathname,0) + myfailed('Aborted.'); + return; +end + +ext = '.mat'; + +%find files in folder +filelist = createtree(pathname,ext); +numfiles = length(filelist); + +for loop = 1:numfiles + [filepath{loop},filename{loop}] = fileparts(filelist{loop}); +end + +%add to work list +addtolistmat(filepath,filename); + + +%------------------------------------- +function importlist_Callback(filetype) +%------------------------------------- +global DATA WL + +temp = pwd; +cd(DATA.Pref.datapath); +[filename,pathname] = myuigetfile(... + '*.*','Select Excel file to load worklist from'); +cd(temp); + +fullfilename=[pathname filesep filename]; + +%Load Excel file +[~, ~,textfromfile] = xlsread(fullfilename); +%remove header and extract correct amount of columns +WLfromfile=textfromfile(2:end,1:4); + +%format variable anonymize in WL from file + +if isempty(WL) + WL=WLfromfile; +else + WL=[WL; WLfromfile]; %add to current WL +end + +updatelist; + +%------------------------------------- +function clearlist_Callback(filetype) +%------------------------------------- +global WL + +WL=[]; +updatelist; + +%----------------------------------- +function savelist_Callback +%----------------------------------- +global WL DATA + +getlistfromgui; + +gui=DATA.GUI.Anonymization; +titles=get(gui.handles.worklisttable,'ColumnName'); +WLtofile=[titles';WL];%add header row to file + +segment('cell2clipboard',WLtofile,true);%true in order to writetofile + +%------------------------------- +function adddicomfolder_Callback +%------------------------------- +global DATA + +if isempty(DATA) + pathname = myuigetdir(pwd,'Select directory to pseudonymize DICOM files in. Note: recursive behaviour.'); +else + pathname = myuigetdir(DATA.Pref.datapath,'Select directory to pseudonymize DICOM files in. Note: recursive behaviour.'); +end +if isequal(pathname,0) + myfailed('Aborted.',DATA.GUI.Segment); + return; +end + +filesepindex=strfind(pathname,filesep); +lastfilesep=find(filesepindex + h = mywaitbarstart(numfiles,'Pseudonymizing files. Please wait.',1); + corruptedfiles=''; + segment('filecloseall_Callback',true); + for fileloop=1:numfiles + %--- Load file + DATA.Silent = true; %Turn on "silent" mode to avoid to much update on screen when loading etc. + listindex=indextoanonymize(fileloop); + newname=WL{listindex,2}; + filename=WL{listindex,3}; + pathname=WL{listindex,4}; + ext='.mat'; + + disp(dprintf('Loading %s.',filename)); + %Make sure a fresh start + + %---- try + %Load + SET=[]; + load([pathname filesep filename ext],'-mat','setstruct','info'); + + %Assign + if not(isempty(setstruct)) + SET = setstruct; + clear setstruct; + + %Call to intialize all variables correcly after loaded data. + openfile('setupstacksfrommat',1); + segment('renderstacksfrommat'); + + if savekeyfile + output{fileloop+1,1}=newname; + if saveasnewname + output{fileloop+1,2}=newname; + else + output{fileloop+1,2}=filename; + end + output{fileloop+1,3}=filename; + output{fileloop+1,4}=pathname; + output{fileloop+1,5}=SET(1).PatientInfo.Name; + output{fileloop+1,6}=SET(1).PatientInfo.ID; + output{fileloop+1,7}=SET(1).PatientInfo.BirthDate; + if isequal(anontype,'full') + output{fileloop+1,8}=SET(1).PatientInfo.Sex; + output{fileloop+1,9}=SET(1).PatientInfo.Age; + output{fileloop+1,10}=SET(1).PatientInfo.AcquisitionDate; + output{fileloop+1,11}=SET(1).PatientInfo.Length; + output{fileloop+1,12}=SET(1).PatientInfo.Weight; + output{fileloop+1,13}=SET(1).PatientInfo.BSA; + output{fileloop+1,14}=SET(1).PatientInfo.Institution; + end + end + + %anonymize dataset + if isequal(anontype,'full') + tools('anonymoustotal_Callback',true,newname); + elseif isequal (anontype, 'partial') + tools('anonymous_Callback',true,newname); + else + tools('anonymouscorrective_Callback',true,newname); + end + + %Create thumbnails before storing. + calcfunctions('calcdatasetpreview'); + + % Set view settings + DATA.ViewPanels = 1; + DATA.ViewPanelsType = {'one'}; + DATA.ViewMatrix = [1 1]; + DATA.ThisFrameOnly = 0; + DATA.CurrentPanel = 1; + DATA.CurrentTheme = 'lv'; + DATA.CurrentTool = 'select'; + + %Save the file. + disp('Saving...'); + %segment('filesaveall_Callback'); + corrupted=segment('checkcorrupteddataforautomaticsave'); + if corrupted + corruptedfiles=sprintf('%s, %s',corruptedfiles,filename); + mywarning(dprintf('Image file %s seems to be corrupted from last save. Please load and pseudonymize manually to ensure that the image is not corrupted before saving.',filename)); + else + if saveasnewname && not(isequal(filename,newname)) + [sucess,m] = mymovefile([pathname filesep filename ext],[pathname filesep newname ext],'f'); %rename file + if not(sucess) + myfailed(dprintf('Failed to rename file %s',filename)); + else + filemenu('saveallas_helper',pathname,newname); + end + else + filemenu('saveallas_helper',pathname,filename); + end + end + segment('filecloseall_Callback',true); + end + setstruct=[]; + info=[]; %#ok + h = mywaitbarupdate(h); + end + mywaitbarclose(h); + + if isempty(corruptedfiles) + if isequal(anontype,'full') + donestri = 'Patient identity and info removed in the selected .mat files.'; + elseif isequal(anontype,'partial') + donestri = 'Patient identity removed in the selected .mat files.'; + else + donestri = 'Filename and pathname removed in the selected .mat files.'; + end + mymsgbox(donestri,'Done!',DATA.GUI.Segment); + else + myfailed(dprintf('The following files have not been pseudonymized: %s',corruptedfiles),DATA.GUI.Segment); + end + + segment('filecloseall_Callback',true); +catch me + mydispexception(me); + myfailed('Error in pseudonymization process. The files are not correclty pseudonymized. Please review that all filepaths are correct.'); +end + +if savekeyfile + segment('cell2clipboard',output,true);%true in order to writetofile +end + +DATA.Silent=0; + +%------------------------------- +function anonymizedicom_Callback +%------------------------------- +%Anonymize dicom-files according to anonymization type selcted by +%radiobuttons + +global DATA WL + +if isempty(WL) + myfailed('Worklist is empty. Please add files to pseudonymize.'); + return; +end + +%get type of anonymization from radiobutton +gui=DATA.GUI.Anonymization; +if get(gui.handles.fullradiobutton,'value') + anontype='full'; +elseif get(gui.handles.partialradiobutton,'value') + anontype='partial'; +elseif get(gui.handles.correctiveradiobutton,'value') + anontype='corrective'; +else + myfailed('Select which type of pseudonymization to perform.'); + return; +end +if isequal(anontype,'full')||isequal(anontype,'corrective') + myfailed('Only partial pseudonymization is implemented'); + return; +end + +if isequal(anontype,'full') + stri = 'This feature will remove all subject identity and info on the selected DICOM files. Are you sure?'; +elseif isequal(anontype,'partial') + stri = 'This feature will remove subject identity (patient ID, name and birth date) on the selected DICOM files. Are you sure?'; +else + stri = 'This feature will only remove obscure tags which might contain patient name/ID/birthdate without editing the original patient ID/name/birthdate on the selected DICOM files. Are you sure?'; +end + +if ~yesno(stri) + mymsgbox('Aborted.',''); + return; +end + +savekeyfile=get(gui.handles.savelistcheckbox,'value'); + +%update list from gui +getlistfromgui; + +%find which files to anonymize from worklist +anonymize=zeros(size(WL,1),1); +[anonymize(:)]=[WL{:,1}]; +indextoanonymize=find(anonymize); +numfiles=length(indextoanonymize); + +%doublecheck with the user if worklist shall be saved +if not(savekeyfile) + if ~yesno('You have chosen to not save the work list. This will be your only key to identify the subjects. Are you sure that you want to continue without saving the work list?') + return; + end +end +try + silent=true; + showwaitbar=true; + h = mywaitbarstart(numfiles,'Pseudonymizing files. Please wait.',1); + corruptedfiles=''; + for fileloop=1:numfiles + %--- Load file + DATA.Silent = true; %Turn on "silent" mode to avoid to much update on screen when loading etc. + listindex=indextoanonymize(fileloop); + newname=WL{listindex,2}; + foldername=WL{listindex,3}; + pathname=WL{listindex,4}; + + disp(dprintf('Loading %s.',foldername)); + + %recursive anonymisation for current path to the current new name + dicomanonymize(pathname,newname,silent,showwaitbar); + h = mywaitbarupdate(h); + end + mywaitbarclose(h); + + if isempty(corruptedfiles) + if isequal(anontype,'full') + donestri = 'Patient identity and info removed in the selected DICOM files.'; + elseif isequal(anontype,'partial') + donestri = 'Patient identity removed in the selected DICOM files.'; + else + donestri = 'Filename and pathname removed in the selected DICOM files.'; + end + mymsgbox(donestri,'Done!',DATA.GUI.Segment); + else + myfailed(dprintf('The following files have not been pseudonymized: %s',corruptedfiles),DATA.GUI.Segment); + end + + segment('filecloseall_Callback',true); + +catch me + mydispexception(me); + mydisp('Error in pseudonymization process. The files are not correclty pseudonymized.'); +end + +if savekeyfile + savelist_Callback; +end + +DATA.Silent=0; + + +%--------------------------------------------- +function addtolistmat(filepath,filename,newname) +%-------------------------------------------- +global WL + +if nargin<3 + newname=filename; +end + +%initialize WL +if isempty(WL) + numlines=0; + WL=cell(1,4); +else + numlines=size(WL,1); + getlistfromgui; +end + +%add data in WL +numnewlines=length(filepath); +for loop=1:numnewlines + WL{numlines+loop,1}=true;%anonymize + WL{numlines+loop,2}=newname{loop};%default:new name same as filename + WL{numlines+loop,3}=filename{loop}; + WL{numlines+loop,4}=filepath{loop};%filepath in last column +end + +updatelist; + +%--------------------------------------------- +function subdirbatch_Callback %#ok +%--------------------------------------------- + +global DATA + +%select folder +pathname = DATA.Pref.datapath; +pathname = myuigetdir(pathname,'Select a folder (including subfolders) with DICOM files'); + +if isequal(pathname,0) + myfailed('Aborted.'); + return +end + +subdirbatch(pathname) + + +%--------------------------------------------- +function subdirbatch(basefolder) +%-------------------------------------------- + +global WL + +%initialize WL +if isempty(WL) + numlines=0; + WL = cell(1,4); +else + numlines = size(WL,1); + getlistfromgui; +end + +flist = dir(basefolder); + +addtoline = numlines; + +for floop = 1:length(flist) + f = flist(floop); + + if strcmp(f.name, '.') || strcmp(f.name, '..') + continue + end + + if ~f.isdir + continue + end + + % OK, we have a subdir, add it to the list + addtoline = addtoline + 1; + + WL{addtoline,1} = true; + WL{addtoline,2} = f.name; + WL{addtoline,3} = f.name; + WL{addtoline,4} = fullfile(f.folder, f.name); +end + +updatelist; + + +%--------------------------------------------- +function addtolistdicom(filepath,foldername, newname) +%-------------------------------------------- +global WL + +if nargin<3 + newname=cell(size(filepath)); + newname{:}='Hidden'; +end + +%initialize WL +if isempty(WL) + numlines=0; + WL=cell(1,4); +else + numlines=size(WL,1); + getlistfromgui; +end + +%add data in WL +numnewlines=length(filepath); +for loop=1:numnewlines + WL{numlines+loop,1}=true;%anonymize + WL{numlines+loop,2}=newname{loop};%default:new name same as filename + WL{numlines+loop,3}=foldername{loop}; + WL{numlines+loop,4}=filepath{loop};%filepath in last column +end + +updatelist; + +%------------------ +function updatelist +%------------------ +global DATA WL + +gui=DATA.GUI.Anonymization; +set(gui.handles.worklisttable,'Data',WL); +DATA.GUI.Anonymization=gui; + +%----------------------- +function getlistfromgui +%---------------------- +global DATA WL + +gui=DATA.GUI.Anonymization; +WL=get(gui.handles.worklisttable,'Data'); + + +%----------------------------- +function initguisubject +%----------------------------- +%initiate the GUI for pseydonymization for current .mat-file +global DATA SET + +if isempty(SET) + myfailed('This feature applies to open files. Please open the file to pseudonymize, or use the batch pseudonymization features.'); + return +end + +%open figure +DATA.GUI.Anonymization = mygui('anonymizationsubject.fig'); + +fig = DATA.GUI.Anonymization.fig; + +set(fig,'DeleteFcn','anonymization(''deleteguisubject_Callback'')'); + + +%-------------------------- +function deleteguisubject_Callback +%-------------------------- +%close the GUI for pseydonymization for current .mat-file +global DATA + +try + DATA.GUI.Anonymization = close(DATA.GUI.Anonymization); +catch %#ok + delete(gcf); + if isa(DATA,'maingui') + DATA.GUI.Anonymization = []; + end +end + +%----------------------------- +function anonymizesubject_Callback +%----------------------------- +%Anonymize current .mat-file according to anonymization type selcted by +%radiobuttons + +global DATA + +handles = DATA.GUI.Anonymization.handles; + +if get(handles.partialradiobutton,'value') + tools('anonymous_Callback'); %partial +elseif get(handles.extensiveradiobutton,'value') + tools('anonymoustotal_Callback'); %extensive +end + +deleteguisubject_Callback; + diff --git a/source/anonymizationdicom.fig b/source/anonymizationdicom.fig new file mode 100644 index 0000000..265c8e7 Binary files /dev/null and b/source/anonymizationdicom.fig differ diff --git a/source/anonymizationmat.fig b/source/anonymizationmat.fig new file mode 100644 index 0000000..1189672 Binary files /dev/null and b/source/anonymizationmat.fig differ diff --git a/source/anonymizationsubject.fig b/source/anonymizationsubject.fig new file mode 100644 index 0000000..e400490 Binary files /dev/null and b/source/anonymizationsubject.fig differ diff --git a/source/atrialscar.m b/source/atrialscar.m index 3daedbf..22c9393 100644 --- a/source/atrialscar.m +++ b/source/atrialscar.m @@ -25,7 +25,7 @@ global SET NO DATA SET(NO).AtrialScar = []; -drawfunctions('drawimagepanel',DATA.CurrentPanel); +drawfunctions('drawpanel',DATA.CurrentPanel); segment_main('updatevolume'); %-------------------- @@ -71,111 +71,26 @@ function update(no) dist = sqrt((xr-circshift(xr,[1 0])).^2+(yr-circshift(yr,[1 0])).^2)/10; %10 to convert to cm totarea = totarea+sum(dist(:))*slicethickness; totscararea = totscararea+sum(dist(:))*slicethickness*(sum(rr))/length(rr); - end; -end; + end +end SET(no).AtrialScar.TotArea = totarea; SET(no).AtrialScar.Percentage = (totscararea/totarea)*100; -drawfunctions('drawimagepanel',DATA.CurrentPanel); +%drawfunctions('drawimagepanel',DATA.CurrentPanel); +drawfunctions('drawpanel',DATA.CurrentPanel); segment_main('updatevolume'); -%--------------------------- -function drawimageone(no,panel) %#ok -%--------------------------- -global DATA SET - -if isequal(get(DATA.Handles.hidescaricon,'state'),'on') - hide = true; -else - hide = false; -end; - -if ~hide - x = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - - logind = SET(no).AtrialScar.Result(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - x1 = x(logind); - y1 = y(logind); -else - x1 = NaN; - y1 = NaN; -end; - -if isempty(x1) - x1 = NaN; - y1 = NaN; -end; - -DATA.Handles.atrialscarcontour(panel) = plot(DATA.Handles.imageaxes(panel),y1,x1,'y.'); - -%---------------------------------- -function drawimagemontage(no,panel) %#ok -%---------------------------------- -global DATA SET - -if isequal(get(DATA.Handles.hidescaricon,'state'),'on') - hide = true; -else - hide = false; -end; - -if ~hide - x = SET(no).RVEndoXView(:,SET(no).CurrentTimeFrame); - y = SET(no).RVEndoYView(:,SET(no).CurrentTimeFrame); - - logind = vertcat( ... - SET(no).AtrialScar.Result,true(1,SET(no).TSize,SET(no).ZSize)); - x1 = x(logind(:)); - y1 = y(logind(:)); -else - x1 = NaN; - y1 = NaN; -end; - -if isempty(x1) - x1 = NaN; - y1 = NaN; -end; - -DATA.Handles.atrialscarcontour(panel) = plot(DATA.Handles.imageaxes(panel),y1,x1,'y.'); - -%----------------------------- -function drawsliceone(no,panel) %#ok -%----------------------------- -global DATA SET - -if isequal(get(DATA.Handles.hidescaricon,'state'),'on') - hide = true; -else - hide = false; -end; - -if ~hide - x = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - - logind = SET(no).AtrialScar.Result(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - x1 = x(logind); - y1 = y(logind); -else - x1 = NaN; - y1 = NaN; -end; - -set(DATA.Handles.atrialscarcontour(panel),'ydata',x1,'xdata',y1,'color',[1 1 0]); - %----------------------------------------- function manualdraw_Buttonup(no,type,xr,yr) %#ok %----------------------------------------- -%Callback called from manualdraw_Buttonup in segment_main +%Callback called from buttonupfunctions.m global SET if isempty(SET(no).AtrialScar) initscar(no); %Initalize data structure -end; +end %Create a mask mask = segment('createmask',[SET(no).XSize SET(no).YSize],xr,yr); @@ -188,12 +103,12 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok ind = find(z>0.5); %logical index %Assign -switch type +switch lower(type) case 'scar' SET(no).AtrialScar.Manual(ind,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = int8(1); case 'rubberpen' SET(no).AtrialScar.Manual(ind,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = int8(-1); -end; +end update(no); @@ -227,12 +142,12 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok if contcheck>0 myfailed('Slices are not contigous. Missing segmentation in some slice.'); return; -end; +end if length(slices)<2 myfailed('Expected at least two slices for atrial scar visualization.'); return; -end; +end %Extract tf,slices x = squeeze(x(:,tf,slices)); @@ -244,7 +159,7 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok for loop = 1:length(slices) tempmask = segment('createmask',[SET(NO).XSize SET(NO).YSize],x(:,loop),y(:,loop)); mask(:,:,loop) = tempmask; -end; +end %--- Create smoothing filter n = 7; @@ -286,7 +201,7 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok ind = sub2ind([SET(NO).XSize SET(NO).YSize length(slices)],round(xr2),round(yr2),repmat(loop,size(xr2))); mask(ind) = 1; end -end; +end %--- Smooth scar mask % originalmask = mask; @@ -303,7 +218,7 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok % cdata(cdata<(maxv/2)) = 0; if maxv==0 maxv = 1; -end; +end cdata = 0.2+0.8*cdata/maxv; %--- Scale vertices before visualization @@ -312,7 +227,7 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok fv.vertices(:,3) = fv.vertices(:,3)*(SET(NO).SliceThickness+SET(NO).SliceGap); %--- Display it -figure(12); +fig = figure(12); clf; h = patch(fv); set(h,'cdata',cdata,'facecolor','interp','facealpha',0.7,'edgealpha',0); @@ -321,6 +236,6 @@ function manualdraw_Buttonup(no,type,xr,yr) %#ok %set(h,'edgealpha',0); axis off image; colormap(hot); -cameratoolbar(12); +cameratoolbar(fig); set(gca,'clim',[0 1]); diff --git a/source/autocrop.p b/source/autocrop.p index 01a72f3..505fc55 100644 Binary files a/source/autocrop.p and b/source/autocrop.p differ diff --git a/source/autocropall.p b/source/autocropall.p index 6bd3bb3..7777e84 100644 Binary files a/source/autocropall.p and b/source/autocropall.p differ diff --git a/source/autocropallgui.fig b/source/autocropallgui.fig new file mode 100644 index 0000000..33f7edc Binary files /dev/null and b/source/autocropallgui.fig differ diff --git a/source/autocropallgui.p b/source/autocropallgui.p new file mode 100644 index 0000000..a9097b7 Binary files /dev/null and b/source/autocropallgui.p differ diff --git a/source/autosave.m b/source/autosave.m new file mode 100644 index 0000000..82c9e68 --- /dev/null +++ b/source/autosave.m @@ -0,0 +1,192 @@ +function [varargout] = autosave(varargin) +%Tools for autosaving + +%Einar Heiberg + +%Autosave was included many years ago in Segment but is now re-introduced +%in 2020-10-17. Previous implementation was problematic due to overwriting, +%and also wrote to working folder that could have been a slow network disc. +%New implementation writes series of files to getpreferencespath. +% +%Autosave clears files such as: +% 1) there no more than 500 MB in old files (=> max space 1 GB) +% 2) older files than 24 hours. +% 3) no more than 10 files stored. +% +%Potential problems with new implementation +%1) Potential to get non anonymized data in getpreferencespath +%2) If the files are very big then a lot of data will be in the getpreferencespath (max 1GB) +%3) There is no guarantee that the files are save in a bad state du to +%ongoing computations, some precautions are performed. + +%macro_helper(varargin{:}); %No need for macro recorder +[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard + +%------------ +function init %#ok +%------------ +%Init function check if should start timer + +global DATA + +if DATA.Pref.AutoSave + startit; +else + DATA.AutoSaveTimer = []; +end + +%--------------- +function startit +%--------------- +%Starts the timer + +global DATA + +if ~isfield(DATA,'AutoSaveTimer') + DATA.AutoSaveTimer = []; +end + +%This code is inspired from sectra.m +if ~isempty(DATA.AutoSaveTimer) && isa(DATA.AutoSaveTimer,'timer') + %it is a timer, ensure it is stopped properly + stop(DATA.AutoSaveTimer); + delete(DATA.AutoSaveTimer); +end + +t = 15*60; %15 minutes in seconds +DATA.AutoSaveTimer = timer('StartDelay',t,'Period',t,'ExecutionMode','fixedSpacing'); +DATA.AutoSaveTimer.TimerFcn = 'autosave(''doautosave'')'; +start(DATA.AutoSaveTimer); +disp('Autosave timer started.'); + +%-------------- +function stopit +%-------------- +%Stop autosave timer + +global DATA + +%Try to cleanup +try + cleanup; +catch me + disp('Could not perform cleanup before stopping autosave'); + mydispexception(me); +end + +%Try to stop +try + stop(DATA.AutoSaveTimer); + delete(DATA.AutoSaveTimer); + DATA.AutoSaveTimer = []; + disp('Autosave time deleted.'); +catch me + disp('Something went wrong stopping autosave timer.'); + mydispexception(me); +end + +%------------------ +function doautosave %#ok +%------------------ +%Performs the autosave, first performs cleanup + +global DATA + +%Do not save if no data loaded. +if ~DATA.DataLoaded + return; +end + +%Try to cleanup prior to save +try + cleanup; +catch me + disp('Could not perform cleanup.'); + mydispexception(me); +end + +%check if there is 'myworkon' running +pointer = get(DATA.imagefig,'pointer'); + +while isequal(pointer,'watch') + pause(5); %pause 5 seconds to wait for ongoing computations to finish, user interface is not locked while we perform pause + pointer = get(DATA.imagefig,'pointer'); +end + +%Now the current pointer is no longer a waitbar, this indicates to use that +%it is relatively safe to do autosave + +%Save it +topatientdatabase = false; +silent = true; +pathname = getpreferencespath; +filename = sprintf('autosave-%s.mat',datestr(now,'yyyymmddTHHMMSS',now)); +h = msgbox(dprintf('Autosaving %s%s%s',pathname,filesep,filename)); %Reason for msgbox instead of mymsgbox is that msgbox is non modular (i.e code does not stop and wait for ok). +disp(sprintf('Autosaving %s%s%s',pathname,filesep,filename)); %#ok +filemenu('saveallas_helper',pathname,filename,topatientdatabase,silent) +disp('Autosave done.'); + +try + delete(h); %Try to delete the message box +catch +end + +%--------------- +function cleanup +%--------------- +%Removes old autosaves + +%Removes: +%1) autosaves older than 24 hours +%2) only keeps 4 files (in practise there will be 5 files as cleanup is +%called prior to doautosave. + +pathname = getpreferencespath; + +%Get potential autosave files to delete +f = dir([pathname filesep 'autosave*.mat']); + +if isempty(f) + disp('No autosave files to delete.'); + return; +end + +disp('Checking for autosave files to clean.'); + +%Files are returned alphanumerically, we should delete "the first ones" +numfiles = length(f); + +%find cumulative size of files, counting backwards +cumbytes = zeros(numfiles,1); +totbytes = 0; +for loop = numfiles:-1:1 + totbytes = totbytes + f(loop).bytes; + cumbytes(loop) = totbytes; +end + +%Delete so that there is no more than 500 MB stored +bytelimit = 500*1024*1024; +dodelete = cumbytes>bytelimit; + +%Also delete old files +fileage = now-cat(1,f(:).datenum); %unit is days +dodelete = dodelete | (fileage>1) ; %files older than 24 hours + +if sum(~dodelete)>10 + ind = find(~dodelete); + dodelete(ind(1)) = true; %delete the first one +end + +%loop over to delete +if sum(dodelete)>0 + for loop = 1:length(dodelete) + if dodelete(loop) + disp(sprintf('Deleting autosave file %s',f(loop).name)); %#ok + delete([pathname filesep f(loop).name]); + end + end +else + disp('No files to delete.'); +end + + diff --git a/source/avplane.fig b/source/avplane.fig index f133058..9996d1e 100644 Binary files a/source/avplane.fig and b/source/avplane.fig differ diff --git a/source/avplane.p b/source/avplane.p index 9e36fb0..385c085 100644 Binary files a/source/avplane.p and b/source/avplane.p differ diff --git a/source/axestable.m b/source/axestable.m index 17b774f..3b9aed8 100644 --- a/source/axestable.m +++ b/source/axestable.m @@ -121,11 +121,11 @@ function clearAllValues(obj,clearStr,draw) end %set all values to clearStr in table. for loop=1:length(obj.Key) %Update all values. - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) obj.Key{loop}.values{vloop}=clearStr; end if draw&¬(obj.createHandles) - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) set(obj.Key{loop}.valuesHandle{vloop},'String',clearStr); end end @@ -148,11 +148,11 @@ function clearByUnit(obj,unit,clearStr,draw) for loop=1:length(obj.Key) %Update all values. if strcmp(obj.Key{loop}.Unit,unit) - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) obj.Key{loop}.values{vloop}=clearStr; end if draw&¬(obj.createHandles) - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) set(obj.Key{loop}.valuesHandle{vloop},'String',clearStr); end end @@ -186,12 +186,12 @@ function hide(obj) %----------------- function draw(obj) %----------------- - if obj.NbrTables==0, + if obj.NbrTables==0 disp('No tables to draw'); return end - if obj.hidden && not(obj.createHandles), + if obj.hidden && not(obj.createHandles) return %dont do anything when object is invisible. end @@ -215,7 +215,7 @@ function draw(obj) set(obj.Table{loop}.Handle,'String',stri,'color',obj.fontcolor) end for loop=1:length(obj.Key) %Update all values. - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) stri=obj.parseValue(obj.Key{loop}.values{vloop}); set(obj.Key{loop}.valuesHandle{vloop},... 'String',stri,... @@ -260,7 +260,7 @@ function addTable(obj,title,col,nbrValues,colsize) if nargin<5 obj.Table{obj.NbrTables}.xstep=ones(1,col)*obj.FigWith/col; elseif sum(colsize)<1+1e-5&&sum(colsize)>1-1e-5 &&... - length(colsize)==col, + length(colsize)==col obj.Table{obj.NbrTables}.xstep=colsize*(obj.FigWith-obj.xstart); else obj.Table{obj.NbrTables}.xstep=ones(1,col)*obj.FigWith/col; @@ -292,12 +292,12 @@ function addTableHead(obj,column_names) return end - if obj.Table{obj.NbrTables}.nbrValues+1~=length(column_names), + if obj.Table{obj.NbrTables}.nbrValues+1~=length(column_names) disp('addTableHeader: Wrong number or fields.'); return; end - if obj.Table{obj.NbrTables}.CurCols~=1, + if obj.Table{obj.NbrTables}.CurCols~=1 disp('addTableHeader: Call this method directly after addTable'); return; end @@ -325,7 +325,7 @@ function addKey(obj,key,name,unit,values) error('Forbidden to add Keys once table is drawn') end - if obj.NbrTables==0, + if obj.NbrTables==0 error('No table, call newtable'); end @@ -333,7 +333,7 @@ function addKey(obj,key,name,unit,values) values={values}; end - if length(values)~=obj.Table{obj.NbrTables}.nbrValues, + if length(values)~=obj.Table{obj.NbrTables}.nbrValues error('Wrong number of values for current table'); end @@ -356,7 +356,7 @@ function addKey(obj,key,name,unit,values) obj.Key{nbr_keys}.valuesXpos=[]; obj.Key{nbr_keys}.valuesYpos=[]; - for loop=1:length(values),%figure out postition + for loop=1:length(values) %figure out postition obj.Key{nbr_keys}.valuesXpos(loop)=obj.xpos; obj.Key{nbr_keys}.valuesYpos(loop)=obj.ypos; obj.xpos=obj.xpos+obj.Table{obj.NbrTables}.xstep(obj.Table{obj.NbrTables}.CurCols); @@ -364,7 +364,7 @@ function addKey(obj,key,name,unit,values) end if obj.Table{obj.NbrTables}.CurCols>... - obj.Table{obj.NbrTables}.Cols, + obj.Table{obj.NbrTables}.Cols obj.ypos=obj.ypos+obj.Table{obj.NbrTables}.ystep; obj.Table{obj.NbrTables}.CurCols=1; obj.xpos=obj.xstart; @@ -374,7 +374,7 @@ function addKey(obj,key,name,unit,values) %--------------------- function addSpace(obj) %--------------------- - if obj.NbrTables==0, + if obj.NbrTables==0 obj.ypos=obj.ypos+obj.ystep; else obj.xpos=obj.xstart; @@ -397,14 +397,14 @@ function updateKey(obj,key,values,draw) end for loop=1:length(obj.Key) - if strcmp(obj.Key{loop}.Key,key), - if length(values)~=length(obj.Key{loop}.values), + if strcmp(obj.Key{loop}.Key,key) + if length(values)~=length(obj.Key{loop}.values) error('Nbr of values does not match'); end obj.Key{loop}.values=values; if draw&&~obj.createHandles - for vloop=1:length(values), + for vloop=1:length(values) stri=obj.parseValue(obj.Key{loop}.values{vloop}); set(obj.Key{loop}.valuesHandle{vloop},'String',stri); end @@ -436,7 +436,7 @@ function updateName(obj,key,names,draw) end for loop=1:length(obj.Key) - if strcmp(obj.Key{loop}.Key,key), + if strcmp(obj.Key{loop}.Key,key) % if length(names)~=length(obj.Key{loop}.Name), % error('Nbr of names does not match'); % end @@ -459,7 +459,7 @@ function updateUnit(obj,key,unit,draw) end for loop=1:length(obj.Key) - if strcmp(obj.Key{loop}.Key,key), + if strcmp(obj.Key{loop}.Key,key) % if length(names)~=length(obj.Key{loop}.Name), % error('Nbr of names does not match'); % end @@ -493,7 +493,7 @@ function keyVisible(obj,key,visible,draw) draw=false; end for loop=1:length(obj.Key) - if strcmp(obj.Key{loop}.Key,key), + if strcmp(obj.Key{loop}.Key,key) obj.Key{loop}.showKey=visible; if visible @@ -503,7 +503,7 @@ function keyVisible(obj,key,visible,draw) end if draw&¬(obj.createHandles) set(obj.Key{loop}.keyHandle,'Visible',vis); - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) set(obj.Key{loop}.valuesHandle{vloop},'Visible',vis); end end @@ -553,12 +553,12 @@ function firstdraw(obj) obj.Table{loop}.Title,obj.Table{loop}.xpos,obj.Table{loop}.ypos); obj.Table{loop}.LineHandle = putline(obj,obj.Table{loop}.ypos); - if isfield(obj.Table{loop},'Head'), + if isfield(obj.Table{loop},'Head') obj.Table{loop}.Head.LineHandle=... putline(obj,obj.Table{loop}.Head.lineypos); col_lenth=length(obj.Table{loop}.Head.Title); x_pos=[obj.xstart obj.xstart+cumsum(obj.Table{obj.NbrTables}.xstep(1:end-1))]; - for vloop=1:col_lenth*obj.Table{loop}.Head.Repeat; + for vloop=1:col_lenth*obj.Table{loop}.Head.Repeat ind=mod(vloop-1,col_lenth)+1; obj.Table{loop}.Head.TitleHandle{vloop}=putstring(obj,... obj.Table{loop}.Head.Title{ind}, x_pos(vloop) ,... @@ -637,12 +637,12 @@ function setVisible(obj,value) for loop=1:length(obj.Key) %Update all values. if obj.Key{loop}.showKey set(obj.Key{loop}.keyHandle,'Visible',value); - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) set(obj.Key{loop}.valuesHandle{vloop},'Visible',value); end else set(obj.Key{loop}.keyHandle,'Visible','off'); - for vloop=1:length(obj.Key{loop}.values), + for vloop=1:length(obj.Key{loop}.values) set(obj.Key{loop}.valuesHandle{vloop},'Visible','off'); end end diff --git a/source/balloonimage.mexw32 b/source/balloonimage.mexw32 deleted file mode 100644 index 9517906..0000000 Binary files a/source/balloonimage.mexw32 and /dev/null differ diff --git a/source/bullseye.fig b/source/bullseye.fig index dc9eb64..e0bd920 100644 Binary files a/source/bullseye.fig and b/source/bullseye.fig differ diff --git a/source/buttondownfunctions.m b/source/buttondownfunctions.m new file mode 100644 index 0000000..ffbb9a9 --- /dev/null +++ b/source/buttondownfunctions.m @@ -0,0 +1,1891 @@ +function buttondownfunctions(varargin) +% Functions for buttondowns + +% Broken out by Klas + +%Invoke subfunction +macro_helper(varargin{:}); %future macro recording use +feval(varargin{:}); % FEVAL switchyard + +%------------------------------------- +function buttondown(panel,currenttool) %#ok +%------------------------------------- +global DATA SET +persistent ismaxnumrois + +scale = viewfunctions('getscale',panel); +no = DATA.ViewPanels(panel); +clicktype = get(DATA.fig,'SelectionType'); + +%store the current panel after graphical update and return. The +%procedure is that first the panel is selected then you can start selecting +%slices and rois. +if DATA.CurrentPanel ~= panel + viewfunctions('switchpanel',panel) + DATA.updatevolumeaxes; + return +end + +%if montage select slice +if any(strcmp(DATA.ViewPanelsType{panel},{'montagesegmented','montagerow','montage'})) + [x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + slice = viewfunctions('clickedslice',panel,x,y); + if ~isempty(slice) + if slice ~= SET(no).CurrentSlice && ismember(currenttool,{'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp','GeneralPenInterp'}) + SET(no).StartSlice = slice; + SET(no).EndSlice = slice; + SET(no).CurrentSlice = slice; + drawfunctions('drawno',no); + return; + else + SET(no).StartSlice = slice; + SET(no).EndSlice = slice; + SET(no).CurrentSlice = slice; + drawfunctions('drawno',no); + end + else + return + end +end + +%Only measures available for these panels +if any(strcmp(DATA.ViewPanelsType{panel},{'hla','gla','vla'})) + if ~strcmp(currenttool,'Measure') + if ~strcmp(currenttool,'select') + return + end + end +end + +%This enables undo. +if any(ismember(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','cor3DP','speedim'})) + %segment3dp.tools('enableundo') +else + tools('enableundo',no); +end + +switch clicktype + case 'normal' + %these are used to store information about rightclick. Type tells us + %which context menu to use objectind tells us which index we right + %clicked next to. + DATA.LastObjectType = []; + DATA.LastObject = []; + case 'open' + %this is the double click + % check the current tool, since double click option is only valid for + % select tool + if ~strcmp(currenttool,'select')|| strcmp(DATA.CurrentTheme,'3dp') %|| isdeployed + return + end + if isempty(DATA.LastView) + % save the last view + DATA.LastView.ViewPanels = DATA.ViewPanels; + DATA.LastView.ViewPanelsType = DATA.ViewPanelsType; + DATA.LastView.ViewMatrix = DATA.ViewMatrix; + DATA.LastView.CurrentPanel = DATA.CurrentPanel; + DATA.LastView.NormalZoomState = {SET.NormalZoomState}; + if numel(DATA.ViewPanels) == 1 + % check whether to switch to one panel view + switch DATA.ViewPanelsType{1} + case 'one' + newview = 'montage'; + case {'montage', 'montagerow'} + newview = 'one'; + otherwise + return + end + viewfunctions('setviewtype',newview); + else + % go to one view + DATA.ViewMatrix = [1,1]; + viewfunctions('setview',DATA.ViewMatrix(1),DATA.ViewMatrix(2),[]); + end + return + else + %reset to previous view + try + DATA.ViewPanels = DATA.LastView.ViewPanels; + DATA.ViewPanelsType = DATA.LastView.ViewPanelsType; + DATA.ViewMatrix = DATA.LastView.ViewMatrix; + DATA.CurrentPanel = DATA.LastView.CurrentPanel; + panelstodo = find(DATA.LastView.ViewPanels); + for actpanel = panelstodo + no = DATA.ViewPanels(actpanel); + SET(no).NormalZoomState = DATA.LastView.NormalZoomState{no}; + end + viewfunctions('setview',DATA.ViewMatrix(1),DATA.ViewMatrix(2),DATA.ViewPanels); + catch me + mydispexception(me); + end + DATA.LastView = []; + end + + case 'alt' + if ~strcmp(DATA.CurrentTheme,'3dp') + if SET(no).EndoInterpOngoing || SET(no).EpiInterpOngoing ||... + SET(no).RVEndoInterpOngoing || SET(no).RVEpiInterpOngoing + tools('connectinterpolation',no); + return + end + [y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system + slice = viewfunctions('clickedslice',panel,y,x); + slices = viewfunctions('slicesinpanel',panel); + + %normalize clicked position to contour domain + [yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices == slice,1)); + x = x/scale - (xl-1)*SET(no).XSize; + y = y/scale - (yl-1)*SET(no).YSize; + stateandicon = viewfunctions('iconson','point'); + pointstate = stateandicon{1}; + modifier = get(gcbf, 'Currentmodifier'); + if pointstate && not(isempty(modifier)) && strcmp(modifier,'control') + % if place annotation point is on then place point where the right + % click was done + [~,pointind] = findfunctions('closestpoint',panel,x,y); + + %This way if you click close to a measure you drag that point of the + %measure. + DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''point_buttonup'',%d,%d,%d)',panel,pointind,slice); + return + else + DATA.LastClickType = clicktype;% helper in findfunctions(closestmeasure) + [type,objectind] = findfunctions('closestobject',panel,x,y); + %place context menu. which one is triggered depends on the + %closestobject + DATA.LastObjectType = type; + DATA.LastObject = [objectind,slice,SET(no).CurrentTimeFrame]; + viewfunctions('placecontextmenu',panel,type,objectind); + DATA.LastClickType = []; + return + end + else + %3DP and right click + p = get(DATA.fig,'CurrentPoint'); + [r,g,b] = segment3dp.tools('getclickedposition3DP'); + %SET(no).LevelSet.View.RSlice = r; %Store + %SET(no).LevelSet.View.GSlice = g; + %SET(no).LevelSet.View.BSlice = b; + + [x,y,z] = segment3dp.tools('rgb2xyz',r,g,b); + %[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel))%this needs to transformed to the stored coordinate system + [type,objectind] = findfunctions('closestobject',panel,x,y,z); + switch type + case 'Image' + set(DATA.Handles.view2dcontextmenu,'Position',p,'Visible','on'); + case 'Point' + DATA.LastObject = [objectind z 1]; %1=timeframe + set(DATA.Handles.point3dpcontextmenu,'Position',p,'Visible','on'); + end + return + end + case 'extend' + if ~strcmp(DATA.CurrentTheme,'3dp') + if SET(no).EndoInterpOngoing || SET(no).EpiInterpOngoing ||... + SET(no).RVEndoInterpOngoing || SET(no).RVEpiInterpOngoing + tools('connectinterpolation',no) + return + end + end + if ~strcmp(DATA.CurrentTool,'Measure')% && ~strcmp(DATA.CurrentTool,'spliteraser') + %Do panning of current image + pan_buttondown(panel); + return + end +end + +%check if number of points, rois or measurements in current slice is larger than 20 then give +%message that this is not supported. + +%Rois +if (not(isempty(regexpi('roi',currenttool))) || not(isempty(regexpi('roiput',currenttool)))... + || not(isempty(regexpi('roiballoon',currenttool)))) && strcmp(DATA.ViewPanelsType{panel},'one') + %check number of rois in current slice + numrois = sum(cellfun(@(x) any(~isempty(x)) && x==SET(no).CurrentSlice,{SET(no).Roi.Z})); + if numrois >=10 %isfield(DATA.Handles,'roitext') && numrois>=length(DATA.Handles.roitext) + if isempty (ismaxnumrois) + ismaxnumrois = true; + mymsgbox('Cannot have more than 10 ROIs desriptions.','Maximum description reached', DATA.GUI.Segment); + if (isempty(regexpi('roiput',currenttool))) + return + end + end + set(DATA.Handles.roitext(panel,:),'Position',[nan nan]); + end +end + +%Points +if ~isempty(regexpi('point',currenttool)) && strcmp(DATA.ViewPanelsType{panel},'one') + %check number of points in slice current timeframe if in single frame + %mode. + %check maximum number of points in slice all timeframes. + pinslices= SET(no).Point.Z==SET(no).CurrentSlice; + + if not(DATA.ThisFrameOnly) %findindented(DATA.Handles.hideiconholder,'allframesmode') + %all frames mode + uniquetf = unique(SET(no).Point.T(pinslices)); + numpoints = 0; + for t = uniquetf(~isnan(uniquetf)) + tmp = sum(ismember(SET(no).Point.T(pinslices),[t,nan])); + if numpoints=length(DATA.Handles.pointtext) + myfailed('Cannot have more than twenty points in a slice and timeframe') + return + end +end + +%Measurements +if ~isempty(SET(no).Measure) + [measure,slice] = viewfunctions('getmeasurecoords',panel); + nummeasures = 0; + if not(DATA.ThisFrameOnly) %findindented(DATA.Handles.hideiconholder,'allframesmode') + %all frames mode + for tloop = 1:SET(no).TSize + nummeasuresintf = 0; + for loop=1:length(SET(no).Measure) + ziv = round(measure(loop).Z); + ziv = min(ziv):max(ziv); + + if ismember(slice,ziv) && ... + (SET(no).Measure(loop).T==tloop)||(isnan(SET(no).Measure(loop).T)) + nummeasuresintf = nummeasuresintf + 1; + end + end + + if nummeasuresintf>nummeasures + nummeasures = nummeasuresintf; + end + end + else + for loop=1:length(SET(no).Measure) + ziv = round(measure(loop).Z); + ziv = min(ziv):max(ziv); + if ismember(slice,ziv) && ... + (SET(no).Measure(loop).T==SET(no).CurrentTimeFrame)||(isnan(SET(no).Measure(loop).T)) + nummeasures = nummeasures + 1; + end + end + end + + if nummeasures>=length(DATA.Handles.measurementtext) + myfailed('Cannot have more than twenty measurements in a slice and timeframe') + return + end +end + +%Here we toggle to different buttondowns. +switch currenttool + case 'scale' + buttondownfunctions('scale_buttondown',panel) + case 'move' + buttondownfunctions('translate_buttondown',panel) + case 'select' + buttondownfunctions('select_buttondown',panel) + case {'Endo','Epi','RVEndo','RVEpi','Roi','Scar','MO','MaR','ScarRubber','MORubber','MaRRubber','GeneralPen', 'CalciumPen', 'CalciumPenRemove', 'CalciumPenBlue', 'CalciumPenRed', 'CalciumPenLilac' } + buttondownfunctions('pen_buttondown',panel,currenttool) + case {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp','GeneralPenInterp'} + buttondownfunctions('interp_buttondown',panel,currenttool) + case 'Measure' + buttondownfunctions('measure_buttondown',panel) + case 'Contrast' + buttondownfunctions('contrast_buttondown',panel) + case 'RoiPut' + buttondownfunctions('putroi_buttondown',panel,'Roi') + case 'RoiBalloon' + buttondownfunctions('balloon_buttondown',panel,'Roi') + case 'EndoBalloon' + buttondownfunctions('balloon_buttondown',panel,'Endo') + case 'RVEndoBalloon' + buttondownfunctions('balloon_buttondown',panel,'RVEndo') + case 'EpiBalloon' + buttondownfunctions('scale_buttondown',panel) +% buttondownfunctions('balloon_buttondown',panel,'Epi') + case 'crop' + %can only crop in one and montage viewmodes + if ~any(strcmp(DATA.ViewPanelsType{panel},{'one','montage','montagesegmented','montagerow'})) + return + end + buttondownfunctions('crop_buttondown',panel) + case 'Point' + buttondownfunctions('point_buttondown',panel) + case 'cutvessel' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('cutvessel_buttondown',panel) + case 'moveall' + buttondownfunctions('translateall_buttondown',panel) + case 'fastmarching' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('fastmarching_buttondown') + case 'wand' + segment3dp.buttondownfunctions('wand_buttondown') + case 'localwand' + segment3dp.tools('enableundo'); + segment3dp.tools('storeclickedposition'); + segment3dp.tools('wandexpand_Callback'); + case 'localsmooth' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('localsmooth_buttondown') + case 'localclose' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('localclose_buttondown') + case 'localpatch' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('localpatch_buttondown') + case 'localseparate' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('localseparate_buttondown') + case 'localfill' + segment3dp.tools('enableundo'); + segment3dp.buttondownfunctions('localfill_buttondown') + case 'keep' + segment3dp.tools('keepclick_Callback') + case {'localthreshold','draw','rubber'} + segment3dp.tools('enableundo'); + if ~strcmp(clicktype, 'alt') + segment3dp.buttondownfunctions('pen3dp_buttondown',currenttool) + else + if segment3dp.tools('is2d') + segment3dp.tools('split2d_Callback'); + else + segment3dp.tools('split3d_Callback'); + end + end + case 'crop3dp' + crop3dp_buttondown(panel) + case 'box3dp' + segment3dp.tools('enableundo'); + box3dp_buttondown(panel) + case 'click3d' + drawfunctions('drawpoint3D',panel) + case 'addcalcium' + addcalcium_buttondown; + case 'addaortacalcium' + addaortacalcium_buttondown; + case 'addmitralcalcium' + addmitralcalcium_buttondown; + case 'addcoronarycalcium' + addcoronarycalcium_buttondown; +end + +%---------------------------------- +function updatebuttondowns(currenttool,panels) %#ok +%---------------------------------- +%The buttondown is always used within a panel. A buttondown should +%therefore always have the panel as the first argument. +global DATA + +if nargin == 0 || isempty(currenttool) + currenttool = DATA.CurrentTool; +end + +%if still is empty then it hasnt been set yet then assume select. +if isempty(currenttool) + currenttool = 'select'; +end + +if nargin<2 + panels = 1:length(DATA.ViewPanels); +end + +%Set the correct cursor type +switch currenttool + case {'scale','move','Contrast'} + load('pointers.mat','pointer'); + set(DATA.imagefig,... + 'pointer','custom',... + 'pointershapecdata',1+pointer.(lower(currenttool)),... + 'pointershapehotspot',[7 7]); + + case 'select' + set(DATA.imagefig,'pointer','arrow'); + case {'RoiPut','Point'} + load('pointers.mat','pointer'); + set(DATA.imagefig,... + 'pointer','custom',... + 'pointershapecdata',1+pointer.point,... + 'pointershapehotspot',[7 7]); + + case {'Endo','Epi','RVEndo','RVEpi','Roi','Scar',... + 'MO','MaR','ScarRubber','MORubber','MaRRubber',... + 'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp','GeneralPenInterp',... + 'Measure','RoiBalloon','EndoBalloon', 'EpiBalloon','crop','GeneralPen','addcalcium', 'CalciumPen' , 'CalciumPenBlue', 'CalciumPenRed', 'CalciumPenLilac', 'CalciumPenRemove', 'addaortacalcium', 'addmitralcalcium', 'addcoronarycalcium'} + if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') + set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); + else + set(DATA.imagefig,'pointer','custom',... + 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... + 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); + end +end + +viewfunctions('updatetoolhidestate',currenttool); +%Set the buttondowns on each panel +for p = panels + set(DATA.Handles.imageaxes(p).Children,'ButtonDownFcn',sprintf('buttondownfunctions(''buttondown'',%d, ''%s'')',p,currenttool)) + set(DATA.Handles.imageaxes(p),'ButtonDownFcn',sprintf('buttondownfunctions(''buttondown'',%d,''%s'')',p,currenttool)) +end + +%Reset previous motion and buttonup functions just for sure +%set(DATA.fig,'WindowButtonMotionFcn',''); +set(DATA.fig,'WindowButtonMotionFcn','segment(''toggleplaceholdermotion'')'); +set(DATA.fig,'WindowButtonUpFcn',''); + +%Set the CurrentTool field +DATA.CurrentTool = currenttool; + +%----------------------------------- +function contrast_buttondown(panel) %#ok +%----------------------------------- +%Activated by contrast tool, different from resetlight_Callback (above). + +global DATA + +%first we get the clicked position +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,x,y); + +%get x and y size of panel to normalize distance with +xsize = get(DATA.Handles.imageaxes(panel),'xlim'); +xsize = xsize(end)-xsize(1); +ysize = get(DATA.Handles.imageaxes(panel),'ylim'); +ysize = ysize(end)-ysize(1); + +%we set the motion function and the buttonupfunction with input start +%position +set(DATA.fig,'WindowButtonMotionFcn',sprintf('motionfunctions(''contrast_motion'',%d,%d,%f,%f,%f,%f)',panel,slice,x,y,xsize,ysize)); +set(DATA.fig,'WindowButtonUpFcn',sprintf('buttonupfunctions(''contrast_buttonup'',%d,%d,%f,%f,%f,%f)',panel,slice,x,y,xsize,ysize)); + +%----------------------------------------------------------------------------------- +function [interpx,interpy] = interpdrawhelper(interpx,interpy,contourx,contoury,x,y,slice) +%----------------------------------------------------------------------------------- +%Helper fcn to interpdrawbuttondown +%Side effects is update of DATA.Pin. +global DATA SET NO + +% new=true; +tf = SET(NO).CurrentTimeFrame; +if nargin < 7 + slice = SET(NO).CurrentSlice; +end + +%New interpolation point. User has not clicked close to old point. +%Prepare to store point +if isempty(interpx)||... + size(interpx,1)=add many points. + %Interpolate points + newcontourx = contourx(:,tf,slice); + newcontoury = contoury(:,tf,slice); + n = size(contourx,1); + nstep = n/DATA.Pref.NumInterpPoints; %Later take from preferences. + newcontourx = newcontourx(round(1:nstep:n)); + newcontoury = newcontoury(round(1:nstep:n)); + newcontourx = newcontourx(:); + newcontoury = newcontoury(:); + y = []; %Do not add the point + x = []; %Do not add the point + else + %Contour and previous points exist => find closest gap + pinx = [interpx{tf,slice}; y]; + piny = [interpy{tf,slice}; x]; + contx = contourx(:,tf,slice); + conty = contoury(:,tf,slice); + + pinxrep=repmat(pinx',[length(contx) 1]); + contxrep=repmat(contx,[1 length(pinx)]); + pinyrep=repmat(piny',[length(conty) 1]); + contyrep=repmat(conty,[1 length(piny)]); + pindist2cont = (pinxrep-contxrep).^2+(pinyrep-contyrep).^2; + [~,mindistindex] =min(pindist2cont); + [~,sortindex] =sort(mindistindex); + pinx=pinx(sortindex); + piny=piny(sortindex); + + interpx{tf,slice}=pinx; + interpy{tf,slice}=piny; + + y = []; %Do not add the point + x = []; %Do not add the point + end +end + +%Add points +interpx{tf,slice} = [... + interpx{tf,slice} ; ... + newcontourx;y]; +interpy{tf,slice} = [... + interpy{tf,slice} ; ... + newcontoury;x]; + +%---------------------------------------------- +function crop_buttondown(panel) +%---------------------------------------------- +%New buttondown function for cropping. You cannot crop in montage viewmodes only in one. +global DATA + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,x,y); +%5 coords make a box +X = [x,x,x,x,x]; +Y = [y,y,y,y,y]; + +DATA.CursorX = X; +DATA.CursorY = Y; + +DATA.Handles.cursor.Color = 'y'; +DATA.Handles.cursor.LineStyle = '--'; +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''crop_motion'',%d,%f,%f)',panel,x,y); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''crop_buttonup'',%d, %f, %f, %d)',panel,x,y,slice); + +%---------------------------------------------- +function box3dp_buttondown(panel) +%---------------------------------------------- +%New buttondown function for cropping. You cannot crop in montage viewmodes only in one. +global DATA +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +segment3dp.tools('boxmotion',x,y); +set(DATA.fig,'WindowButtonMotionFcn','segment3dp.tools(''boxmotion'')'); +set(DATA.fig,'WindowButtonUpFcn','segment3dp.tools(''levelsetboxbuttonup'')'); + +%---------------------------------------------- +function crop3dp_buttondown(panel) +%---------------------------------------------- +%New buttondown function for cropping. You cannot crop in montage viewmodes only in one. +global DATA +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +segment3dp.tools('boxmotion',x,y); +set(DATA.fig,'WindowButtonMotionFcn','segment3dp.tools(''boxmotion'')'); +set(DATA.fig,'WindowButtonUpFcn','segment3dp.tools(''cropboxbuttonup'')'); + +%---------------------------------------------- +function interp_buttondown(panel,type) %#ok +%---------------------------------------------- +%New buttondown function input is panel and type. The types handled here +%are {EndoInterp,EpiInterp,RVendoInterp,RVepiInterp}. + +global DATA SET + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); +%get closest interpolation point +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',panel,y,x); +slices = viewfunctions('slicesinpanel',panel); + +%normalize clicked position to contour domain +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices == slice,1)); +x = x/scale - (xl-1)*SET(no).XSize; +y = y/scale - (yl-1)*SET(no).YSize; + +%then we need to create a nan matrix with size [numpoints,TSize,ZSize] +if isempty(SET(no).([type(1:end-6),'X'])) + SET(no).([type(1:end-6),'X']) = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + SET(no).([type(1:end-6),'Y']) = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +end + +%then we need to create a cell with size [TSize,ZSize] +if isempty(SET(no).([type,'X'])) + SET(no).([type,'X']) = cell(SET(no).TSize,SET(no).ZSize); + SET(no).([type,'Y']) = cell(SET(no).TSize,SET(no).ZSize); +end + +%Double check so that there is a cell with the correct size for the used +%type +if ~all([size(SET(no).([type,'X']),1)==SET(no).TSize,size(SET(no).([type,'X']),2)==SET(no).ZSize]) + tmpX = cell(SET(no).TSize,SET(no).ZSize); + tmpY = cell(SET(no).TSize,SET(no).ZSize); + sz = size(SET(no).([type,'X'])); + tmpX(1:sz(1),1:sz(2)) = SET(no).([type,'X'])(1:sz(1),1:sz(2)); + tmpY(1:sz(1),1:sz(2)) = SET(no).([type,'Y'])(1:sz(1),1:sz(2)); + SET(no).([type,'X']) = tmpX; + SET(no).([type,'Y']) = tmpY; +end + + +%Old files may have nan vectors in them remove them if so +if all(isnan(SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice})) + SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice} = []; + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice} = []; +end + +[mindist,ind] = findfunctions('closestinterp',panel,type,x,y,slice); +if ~isempty(mindist) && mindist=add many points. + %Interpolate points + newcontourx = SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice); + newcontoury = SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,slice); + n = size(SET(no).([type(1:end-6),'X']),1); + nstep = n/DATA.Pref.NumInterpPoints; %Later take from preferences. + SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}= newcontourx(round(1:nstep:n)); + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice} = newcontoury(round(1:nstep:n)); + + %do graphical update and return + viewfunctions('updatedrawlist',panel); + drawfunctions('drawinterp',panel) + return +else + %closest point on the contour then use this to find the two closest + %interpolation points in different directions along the contour this + %should remove the case where you have close turns on the contour i.e the + %horseshoe + + [val,~] = min(sqrt((x-SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice)).^2+(y-SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,slice)).^2)); + if ~isnan(val) && ~SET(no).([type(1:end-6),'InterpOngoing'])%val< DATA.Pref.ContourAdjustDistance + %First we find the closest point on the contour then we consider + %the distance to each point from the closest points. Since contour + %is equidistantly sampled we can use indexes as our metric. To + %ensure that there is a point close when clicking next to the + %contour we upsample the contour to a thousand points with linear interpolation. + datax = SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice); + datay = SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,slice); + + valueind = ~isnan(datax); + datax = datax(valueind); + datay = datay(valueind); + [contourx,contoury] = calcfunctions('resamplecurve',datax,datay,1000); + [~,ind] = min(sqrt((x-contourx).^2+(y-contoury).^2)); + p2pcontour = zeros(1,length(contourx)); + p2pcontour(1:ind) = ind - 1:-1:0; + p2pcontour(ind+1:end) = 1:length(p2pcontour)-ind; + p2pcontour(end-(floor(length(p2pcontour)/2)-ind)+1:end) = floor(length(p2pcontour)/2):-1:ind + 1; + %then we map each interpolation point to a distance on p2pcontour + %by finding there equivalent on the contour + interpdistalongcontourmap = zeros(1,length(SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice})); + values = interpdistalongcontourmap; + for i = 1:length(SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}) + [val,ind] = min((SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(i)... + -contourx).^2+... + (SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(i)... + -contoury).^2); + interpdistalongcontourmap(i) = ind; + values(i) = val; + end + %find the two minimal distance points + [~,inds] = sort(p2pcontour(interpdistalongcontourmap)); + %JB-2020-08-06 attempt to solve #2107 + % use the closest point ind(1) -> determine index of the + indstart = inds(1); + pstart = [SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(indstart),... + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(indstart)]; + if indstart == 1 + indbefore = length(inds); + else + indbefore = indstart-1; + end + pbefore = [SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(indbefore),... + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(indbefore)]; + if indstart == length(inds) + indafter = 1; + else + indafter = indstart+1; + end + pafter = [SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(indafter),... + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(indafter)]; + pnew = [x,y]; + % calculate angle between closest point-newpoint-left neighbor +% angleft = atan2d((det([pnew-pstart;pleft-pnew])),dot(pnew-pstart,pleft-pnew)) + P0 = [pnew 0]; + P1 = [pbefore 0]; + P2 = [pstart 0]; + n1 = (P2 - P0) / norm(P2 - P0); % Normalized vectors + n2 = (P1 - P0) / norm(P1 - P0); + angleft = atan2d(norm(cross(n1, n2)), dot(n1, n2)); + + P1 = [pafter 0]; + n1 = (P2 - P0) / norm(P2 - P0); % Normalized vectors + n2 = (P1 - P0) / norm(P1 - P0); + angright = atan2d(norm(cross(n1, n2)), dot(n1, n2)); + + anglelimit = 60; + if (indbefore == inds(2) && angleft < anglelimit) + % switch the order of the points + inds(2) = indafter; + elseif(indafter == inds(2) && angright < anglelimit) + inds(2) = indbefore; + end + % end of attempt to solve #2107 + %this should capture the case between the last and first endpoint + if abs(inds(1)-inds(2))>1 + indl = 0; + SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice} = [x;SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}]; + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice} = [y;SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}]; + else + indl = min(inds(1:2)); + SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice} = [SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(1:indl);x;SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(indl+1:end)]; + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice} = [SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(1:indl);y;SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(indl+1:end)]; + end + minind = indl+1; + else + minind = length(SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice})+1; + SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}(minind,1)=x; + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice}(minind,1)=y; + end +end +if SET(no).([type(1:end-6),'InterpOngoing']) + numinterppoints = length(SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}); + numpoints = floor(DATA.NumPoints/15)*(numinterppoints-1); + if numpoints > DATA.NumPoints + numpoints = DATA.NumPoints; + end +else + numpoints = DATA.NumPoints; +end +%here we need to interpolate and store curve into contours. +%The below function removes duplicate points and resamples the contour. +[x,y] = calcfunctions('resamplecurve',SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice},... + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice},numpoints-1); + +%write the results back to the contour field in the SET struct if we've +%placed more than one point +if length(x)>1 + switch type + case 'Roi' + %would be nice to introduce RoiInterpX... + otherwise + if SET(no).([type(1:end-6),'InterpOngoing']) + expectedlength = length(SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice)); + if numpoints < expectedlength + % fill up with NaNs + x = cat(2,x,nan(1,expectedlength-numpoints)); + y = cat(2,y,nan(1,expectedlength-numpoints)); + end + end + SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice)= [x,x(1)]; + SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,slice)= [y,y(1)]; + drawfunctions('drawcontours',panel) + end +elseif length(x) == 1 + SET(no).([type(1:end-6),'InterpOngoing']) = true; + drawfunctions('updateinterpolationsettings',panel,type); +end + +drawfunctions('drawinterp',panel); + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''interp_motion'',%d,''%s'',%d,%d)',panel,type,slice,minind); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''interp_buttonup'',%d,''%s'',%d)',panel,type,slice); + +%------------------------------------- +function orthoview_buttondown(panel,x,y) +%------------------------------------- +%Rotate GLA view using handle on intersection line +global DATA SET + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); + +switch DATA.ViewPanelsType{panel} + case 'orth' + %get the angle handle position + xhan = DATA.Handles.orthoanglehandle.XData; + yhan = DATA.Handles.orthoanglehandle.YData; + + %If sufficiently close to rotation handle trigger rotation else update center position + if norm([xhan yhan]-[x,y])<3 + set(DATA.Handles.cursor,'markersize',20,'marker', '.', 'color', 'w','parent',DATA.Handles.imageaxes(panel)) + set(DATA.fig,'WindowButtonMotionFcn',sprintf('motionfunctions(''glarotatehandle_Motion'',%d)',panel)); + set(DATA.fig,'WindowButtonUpFcn',sprintf('buttonupfunctions(''glarotatehandle_Buttonup'',%d)',panel)); + return + end + + SET(no).HLA.slice = round(y/scale); + SET(no).VLA.slice = round(x/scale); + viewfunctions('setglacenter',no); + case 'hla' + SET(no).VLA.slice = round(x/scale); + SET(no).CurrentSlice = round(y/scale); + viewfunctions('setglacenter',no); + case 'gla' + [vslice,hslice] = calcfunctions('gla2sax',y/scale,x/scale,no); + SET(no).HLA.slice = round(vslice); + SET(no).VLA.slice = round(hslice); + SET(no).CurrentSlice = round(y/scale); + viewfunctions('setglacenter',no); + case 'vla' + SET(no).HLA.slice = round(x/scale); + SET(no).CurrentSlice = round(y/scale); + viewfunctions('setglacenter',no); +end + +%updates the plane intersections +drawfunctions('drawplaneintersections'); + +%update the angle handle for orthoview +DATA.Handles.orthoanglehandle.XData = nan; +DATA.Handles.orthoanglehandle.YData = nan; % this forces the orthoangle handle to refresh after translation +drawfunctions('draworthoanglehandle',find(strcmp('orth',DATA.ViewPanelsType))) + +%empty the DATA.viewim to force creation of new images in all panels but +%the current as it is unnecessary. +for p = 1:length(DATA.ViewPanels) + if p~=panel + calcfunctions('segmentationintersection_helper',p,SET(no).CurrentTimeFrame) %this updates segmentation intersections for the selected panel and current timeframe so it is necessary that intersections are updated for all files at buttonup at buttonup. + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p) + end +end + +%force graphics update +drawnow + +%after doing the current timeframe update we do it for all timeframes +for p = 1:length(DATA.ViewPanels) + if p~=panel + for t = 1:SET(no).TSize + calcfunctions('segmentationintersection_helper',p,t) %this updates stored segmentation intersections for remaining timeframes no graphical update needed. + end + end +end + +%------------------------------ +function scale_buttondown(panel) %#ok +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + magno = SET(no).Flow.MagnitudeNo; +else + magno = no; +end +scale = viewfunctions('getscale',panel); + +%this makes the clicked roi current roi +select_buttondown(panel) +[ystart,xstart] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',panel,ystart,xstart); + +xl = floor(xstart/scale/SET(no).XSize)*SET(no).XSize; +yl = floor(ystart/scale/SET(no).YSize)*SET(no).YSize; +x = xstart/scale - xl; +y = ystart/scale - yl; + +[type,objectind] = findfunctions('closestobject',panel,x,y,slice); + +%below follows the scalables +switch type + case {'Endo','Epi','RVEndo','RVEpi','EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'} + %objectind is not used for contours + if contains(type,'Interp') + tools('connectinterpolation',no,{type}); + %delete Interp at the end + type = type(1:end-6); + else + tools('connectinterpolation',no,{[type,'Interp']}); + end + DATA.CursorX = xl +... + scale*SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice); + DATA.CursorY = yl + ... + scale*SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice); + + case 'Roi' + DATA.CursorX = xl + ... + scale*SET(magno).Roi(objectind).X(:,SET(no).CurrentTimeFrame); + DATA.CursorY = yl + ... + scale*SET(magno).Roi(objectind).Y(:,SET(no).CurrentTimeFrame); + + otherwise + return +end +xc = mean(DATA.CursorX); +yc = mean(DATA.CursorY); +startrad = norm([xstart,ystart]-[xc,yc]); + +%Set marker color +DATA.Handles.cursor.Color = 'w'; +DATA.Handles.cursor.Marker = 'none'; + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +DATA.Handles.cursor.YData = DATA.CursorX; +DATA.Handles.cursor.XData = DATA.CursorY; + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''scale_motion'',%d,%f)',panel,startrad); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''scale_buttonup'',%d,''%s'',%d,%d,%f)',panel,type,objectind,slice,startrad); + +%--------------------- +function translate_buttondown(panel) %#ok +%----------------------- +global DATA SET + +scale = viewfunctions('getscale',panel); +no = DATA.ViewPanels(panel); + +%fix so possible to translate roi in phase image stack +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + magno = SET(no).Flow.MagnitudeNo; +else + magno = no; +end + +[ystart,xstart] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',panel,ystart,xstart); +xl = floor(xstart/scale/SET(no).XSize)*SET(no).XSize; +yl = floor(ystart/scale/SET(no).YSize)*SET(no).YSize; +x = xstart/scale - xl; +y = ystart/scale - yl; + +[type,objectind] = findfunctions('closestobject',panel,x,y,slice); + +%below follows the translateables +switch type + case {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'} %does the same as the later but need to handle dynamic calling differently + tools('connectinterpolation',no,{type}); + %objectind is not used for contours + DATA.CursorX = xl +... + scale*SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice); + DATA.CursorY = yl + ... + scale*SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,slice); + + %When translating we remove the interpolation points + if ~isempty(SET(no).([type,'X'])) + SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice} = []; + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,slice} = []; + drawfunctions('drawinterp',panel) + end + + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = 'none'; + + case {'Endo','Epi','RVEndo','RVEpi'} + tools('connectinterpolation',no,{[type,'Interp']}); + %objectind is not used for contours + DATA.CursorX = xl +... + scale*SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice); + DATA.CursorY = yl + ... + scale*SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice); + + %When translating we remove the interpolation points + if ~isempty(SET(no).([type,'InterpX'])) + SET(no).([type,'InterpX']){SET(no).CurrentTimeFrame,slice} = []; + SET(no).([type,'InterpY']){SET(no).CurrentTimeFrame,slice} = []; + drawfunctions('drawinterp',panel) + end + + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = 'none'; + + case 'Roi' + DATA.CursorX = xl + ... + scale*SET(magno).Roi(objectind).X(:,SET(no).CurrentTimeFrame); + DATA.CursorY = yl + ... + scale*SET(magno).Roi(objectind).Y(:,SET(no).CurrentTimeFrame); + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = 'none'; + case 'Measure' + %measures + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = '+'; + [measure,~] = viewfunctions('getmeasurecoords',panel); + DATA.CursorX = xl + scale * measure(objectind).X; + DATA.CursorY = yl + scale * measure(objectind).Y; + case 'Point' + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = '+'; + DATA.CursorX = xl + scale * SET(no).Point.X(objectind); + DATA.CursorY = yl + scale * SET(no).Point.Y(objectind); + case 'Center' + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = '+'; + DATA.CursorX = xl + scale * SET(no).CenterX; + DATA.CursorY = yl + scale * SET(no).CenterY; + %When translating we remove the center point + if ~isempty(SET(no).([type,'X'])) + % set to a very high number so that the original center cross is not + % seen during motion + SET(no).([type,'X']) = 10^6; + SET(no).([type,'Y']) = 10^6; + drawfunctions('drawcentercross',panel) + end + otherwise + pan_buttondown(panel); + return; +end +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +DATA.Handles.cursor.YData = DATA.CursorX;DATA.Handles.cursor.XData = DATA.CursorY; + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''translate_motion'',%d,%f,%f)',panel,xstart,ystart); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''translate_buttonup'',%d,''%s'',%d,%f,%f,%d)',panel,type,objectind,xstart,ystart,slice); + + +%---------------------------------------------- +function balloon_buttondown(panel,type) %#ok +%---------------------------------------------- +%New buttondown function input is type. The types handled here +%are {Endo,Epi,RVendo,RVepi,Roi}. All temporary drawing is made using the +%cursor object. + +global DATA SET + +no = DATA.ViewPanels(panel); + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,y,x); +slices = viewfunctions('slicesinpanel',panel); +scale = viewfunctions('getscale',panel); +%Set the color of the cursor object which draws the temporary line according to the selected type +switch type + case 'Endo' + DATA.Handles.cursor.Color = 'r'; + DATA.Handles.cursor.LineStyle = '--'; + DATA.Handles.cursor.Marker = 'none'; + useconvhull = 1; + thetasz = 200; + tools('connectinterpolation',no,{'EndoInterp'}) + case 'Epi' + DATA.Handles.cursor.Color = 'g'; + DATA.Handles.cursor.LineStyle = '--'; + DATA.Handles.cursor.Marker = 'none'; + useconvhull = 1; + tools('connectinterpolation',no,{'EpiInterp'}) + case 'RVEndo' + %check if Epi segmentation exists + if isempty(SET(no).EpiX)|| any(isnan(SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) + myfailed('LV Epi segmentation must exist in order to use this tool'); + DATA.Handles.configiconholder.undent('balloonrvendo',0); + DATA.Handles.configiconholder.indent('rvendopen',1); + return + end + tools('connectinterpolation',no,{'RVEndoInterp'}) + DATA.Handles.cursor.Color = 'm'; + DATA.Handles.cursor.LineStyle = '--'; + DATA.Handles.cursor.Marker = 'none'; + useconvhull = 1; + thetasz = 200; + case 'RVEpi' + DATA.Handles.cursor.Color = 'c'; + DATA.Handles.cursor.LineStyle = '--'; + DATA.Handles.cursor.Marker = 'none'; + useconvhull = 1; + tools('connectinterpolation',no,{'RVEpiInterp'}) + case 'Roi' + if ~DATA.ThisFrameOnly && strcmpi(type,'roi') + clr = 'm'; + else + clr = 'b'; + end + DATA.Handles.cursor.Color = clr; + DATA.Handles.cursor.LineStyle = '--'; + DATA.Handles.cursor.Marker = 'none'; + useconvhull = 1; + thetasz = 200; +end + +%clear interpolation points +%When drawing we remove the interpolation points +if ~any(strcmp(type,{'Roi'})) && ~isempty(SET(no).([type,'InterpX'])) + SET(no).([type,'InterpX']){SET(no).CurrentTimeFrame,slice} = []; + SET(no).([type,'InterpY']){SET(no).CurrentTimeFrame,slice} = []; + drawfunctions('drawinterp',panel) +end + +%normalize clicked position to contour domain +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice,1)); +x = x/scale - (xl-1)*SET(no).XSize; +y = y/scale - (yl-1)*SET(no).YSize; + +%create polar image that can be used in motion and +r = round(min([abs(x-SET(no).XSize),x-1,abs(y-SET(no).YSize),y-1])); +im = SET(no).IM(:,:,SET(no).CurrentTimeFrame,slice); + +%Get polar matrix +DATA.ImP = calcfunctions('imtopolar',im(round(x)-r:round(x)+r,round(y)-r:round(y)+r),0,1,r,thetasz); + +%Draw initial circle with radius 5 using Cursor before the algorithm has found anything +d = 1; +theta = linspace(0,2*pi,DATA.NumPoints); +DATA.CursorX = (d*cos(theta)+y+(yl-1)*SET(no).YSize)*scale; +DATA.CursorY = (d*sin(theta)+x+(xl-1)*SET(no).XSize)*scale; +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +DATA.fig.WindowButtonMotionFcn = sprintf('lvsegmentation(''balloon_motion'',%d,%d,%f,%f,%d)',panel,slice,x,y,useconvhull); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''balloon_buttonup'',%d,''%s'',%d,%d)',panel,type,slice,SET(no).CurrentTimeFrame); + + +%---------------------------------------------- +function putroi_buttondown(panel,type) %#ok +%---------------------------------------------- +%New buttondown function input is type. The types handled here +%are {Endo,Epi,RVendo,RVepi,Roi}. All temporary drawing is made using the +%cursor object. + +global DATA SET +no = DATA.ViewPanels(panel); +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,y,x); +slices = viewfunctions('slicesinpanel',panel); +scale = viewfunctions('getscale',panel); + +%Set the color of the cursor object which draws the temporary line according to the selected type +if ~DATA.ThisFrameOnly && strcmpi(type,'roi') + clr = 'm'; +else + clr = 'b'; +end +DATA.Handles.cursor.Color = clr; +DATA.Handles.cursor.LineStyle = '--'; + +%normalize clicked position to contour domain +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice,1)); +x = x/scale - (xl-1)*SET(no).XSize; +y = y/scale - (yl-1)*SET(no).YSize; + +%Draw initial circle with radius 5 using Cursor before the algorithm has found anything +d = 10; +theta = linspace(0,2*pi,DATA.NumPoints); +DATA.CursorX = (d*cos(theta)'/SET(no).ResolutionY+y + (yl-1)*SET(no).YSize)*scale; +DATA.CursorY = (d*sin(theta)'/SET(no).ResolutionX+x + (xl-1)*SET(no).XSize)*scale; +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''putroi_motion'',%d)',panel); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''pen_buttonup'',%d,''%s'',%d,%d)',panel,type,slice,SET(no).CurrentTimeFrame); + + +%---------------------------------------------- +function pen_buttondown(panel,type) %#ok +%---------------------------------------------- +%New buttondown function input is type. The types handled here +%are {Endo,Epi,RVendo,RVepi}. All temporary drawing is made using the +%cursor object. + +global DATA SET +no = DATA.ViewPanels(panel); +switch type + case {'Endo','Epi','RVEndo','RVEpi'} + tools('connectinterpolation',no,{'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}) +end +viewfunctions('updatetoolhidestate',type); + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,y,x); +%Set the color of the cursor object which draws the temporary line according to the selected type +switch type + case 'Endo' + DATA.Handles.cursor.Color = 'r'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'Epi' + DATA.Handles.cursor.Color = 'g'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'RVEndo' + DATA.Handles.cursor.Color = 'm'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'RVEpi' + DATA.Handles.cursor.Color = 'c'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'Roi' + if DATA.ThisFrameOnly + clr = 'b'; + else + clr = 'm'; + end + DATA.Handles.cursor.Color = clr; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'Scar' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'MO' + DATA.Handles.cursor.Color = 'r'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'MaR' + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'ScarRubber' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.Marker = 'none'; + case 'MaRRubber' + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.Marker = 'none'; + case 'GeneralPen' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = '-'; + DATA.Handles.cursor.Marker = 'none'; + case 'CalciumPen' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.LineWidth = 2; + DATA.Handles.cursor.Marker = 'none'; + case 'CalciumPenBlue' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.LineWidth = 2; + DATA.Handles.cursor.Marker = 'none'; + case 'CalciumPenRed' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.LineWidth = 2; + DATA.Handles.cursor.Marker = 'none'; + case 'CalciumPenLilac' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.LineWidth = 2; + DATA.Handles.cursor.Marker = 'none'; + case 'CalciumPenRemove' + DATA.Handles.cursor.Color = 'y'; + DATA.Handles.cursor.LineStyle = ':'; + DATA.Handles.cursor.LineWidth = 2; + DATA.Handles.cursor.Marker = 'none'; +end + +%Clear the cursorX and cursorY field +DATA.CursorX = []; +DATA.CursorY = []; + +%If scar then the stack must not be timeresolved +if any(strcmp(type,{'Scar','MO','ScarRubber'}))&& SET(no).TSize>1 + myfailed('Tool not enabled for time-resolved data. Perhaps delete time frames?') + indent(DATA.Handles.configiconholder,'select',1); + return; +end + +%If scar then endocardium should exist +if any(strcmp(type,'Scar')) && isempty(SET(no).EndoX) + myfailed('Endocardium segmentation must exist to draw scar.') + return; +end + +%clear interpolation points +%When drawing we remove the interpolation points +if ~any(strcmp(type,{'Scar','MaR','MO','ScarRubber','MaRRubber', 'Roi','CalciumPen','CalciumPenBlue', 'CalciumPenRed', 'CalciumPenLilac', 'CalciumPenRemove'})) && ~isempty(SET(no).([type,'InterpX'])) + SET(no).([type,'InterpX']){SET(no).CurrentTimeFrame,slice} = []; + SET(no).([type,'InterpY']){SET(no).CurrentTimeFrame,slice} = []; + drawfunctions('drawinterp',panel) +end + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''pen_motion'',%d)',panel); +if strcmp(type,'MaR') + DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''pen_buttonup'',%d,''%s'')',panel,type); +else + DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''pen_buttonup'',%d,''%s'',%d,%d)',panel,type,slice,SET(no).CurrentTimeFrame);%last input is doall timeframes +end +%---------------------------------------------- +function measureadd_buttondown(panel,measureind,slice) %#ok +%---------------------------------------------- +%New buttondown function input is type. The types handled here +%are {Endo,Epi,RVendo,RVepi}. All temporary drawing is made using the +%cursor object. + +global DATA + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,x,y); +DATA.CursorX = [DATA.CursorX,x]; +DATA.CursorY = [DATA.CursorY,y]; +DATA.CursorZ = [DATA.CursorZ,slice]; + +if strcmp(DATA.fig.SelectionType, 'normal') + buttonupfunctions('measure_buttonup',panel,measureind,slice); + return +end + +pointind = length(DATA.CursorY); +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''measure_motion'',%d,%d)',panel,pointind); + + +%---------------------------------------------- +function translateall_buttondown(panel) %#ok +%---------------------------------------------- +%button down for translating all existing contours + +global DATA SET + +%retrieve clicked point no in panel, clicked slice, slices in panel and scale +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +no = DATA.ViewPanels(panel); +slice = viewfunctions('clickedslice',panel,y,x); +scale = viewfunctions('getscale',panel); +slices = viewfunctions('slicesinpanel',panel); + +%get parameters for transferring into panel coordinates +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice,1)); + +%set cursor color +DATA.Handles.cursor.Color = 'w'; +DATA.Handles.cursor.LineStyle = '--'; +DATA.Handles.cursor.Marker = 'none'; +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +%Empty out any scrap in CursorX and CursorY container. +DATA.CursorX = []; +DATA.CursorY = []; + +%Retrieve all the existing contours transfer there coordinates to the panel +%coordinates and store into DATA.CursorX/Y +types = {'Endo','Epi','RVEndo','RVEpi'}; + +for i = 1:length(types) + if ~isempty(SET(no).([types{i},'X'])) && ~all(isnan(SET(no).([types{i},'X'])(:,SET(no).CurrentTimeFrame,slice))) + DATA.CursorX =[DATA.CursorX;nan; (SET(no).([types{i},'X'])(:,SET(no).CurrentTimeFrame,slice) + (xl-1)*SET(no).XSize)*scale]; + DATA.CursorY =[DATA.CursorY;nan; (SET(no).([types{i},'Y'])(:,SET(no).CurrentTimeFrame,slice) + (yl-1)*SET(no).YSize)*scale]; + end +end +types = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; +for type = 1:length(types) +%When translating we remove the interpolation points + if ~isempty(SET(no).([types{type},'X'])) + SET(no).([types{type},'X']){SET(no).CurrentTimeFrame,slice} = []; + SET(no).([types{type},'Y']){SET(no).CurrentTimeFrame,slice} = []; + drawfunctions('drawinterp',panel) + end +end + +DATA.Handles.cursor.XData = DATA.CursorY; +DATA.Handles.cursor.YData = DATA.CursorX; + +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''translateall_buttonup'',%d,%f,%f,%d)',panel,x,y,slice); +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''translate_motion'',%d,%f,%f)',panel,x,y); + +%---------------------------------------------- +function pan_buttondown(panel) +%---------------------------------------------- +%button down for panning +global DATA + +%get starting position relative to window this is so that we can obtain the +%movement undependent of the xlim ylim +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +xw = x-DATA.Handles.imageaxes(panel).XLim(1); +yw = y-DATA.Handles.imageaxes(panel).YLim(1); + +%Place the original boundaries in Cursor information fields +DATA.CursorX = DATA.Handles.imageaxes(panel).XLim;%-mean(DATA.Handles.imageaxes(panel).XLim); +DATA.CursorY = DATA.Handles.imageaxes(panel).YLim;%-mean(DATA.Handles.imageaxes(panel).YLim); + +%hide all texts +DATA.Handles.text(panel).Position = [nan,nan]; +% % % for c = 'cygmkwrb' +% % % set(DATA.Handles.([c,'roitext'])(panel,:),'Position',[nan,nan]) +% % % end +set(DATA.Handles.roitext(panel,:),'Position',[nan,nan]) +set(DATA.Handles.measurementtext(panel,:),'Position',[nan,nan]) +set(DATA.Handles.pointtext(panel,:),'Position',[nan,nan]) + +%set motion and buttonup function +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''pan_motion'',%d,%f,%f)',panel,xw,yw); +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''pan_buttonup'',%d)',panel); + +%---------------------------------------------- +function point_buttondown(panel)%#ok %,measureind) +%---------------------------------------------- +%button down for points + +global DATA SET + +no = DATA.ViewPanels(panel); +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,y,x); + +%Set the color of the cursor object which draws the temporary line according to the selected type +DATA.Handles.cursor.Color = 'w'; +DATA.Handles.cursor.Marker = '+'; +DATA.Handles.cursor.MarkerSize = 8; + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +%For 3dp the slices is empty +if ~any(strcmp(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','speedim','cor3DP'})) + + slices = viewfunctions('slicesinpanel',panel); + scale = viewfunctions('getscale',panel); + %get montage coordinates of clicked position + [yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice,1)); + + %Find closest point in current timeframe and slice + try + [pointdist,pointind] = findfunctions('closestpoint',panel,x/scale - (xl-1)*SET(no).XSize,... + y/scale - (yl-1)*SET(no).YSize,slice); + catch + pointdist = Inf; + pointind = []; + end +else + %Find closest 3dp point + [pointdist,pointind] = findfunctions('closestpoint3dp',panel,x,y,slice); +end +%If it after the above still is empty create new measure +if isempty(pointind) || pointdist>DATA.Pref.ContourAdjustDistance + pointind = length(SET(no).Point.X)+1; +end + +%plot clicked position +DATA.Handles.cursor.XData = y; +DATA.Handles.cursor.YData = x; + +%This way if you click close to a measure you drag that point of the +%measure. +DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''point_buttonup'',%d,%d,%d)',panel,pointind,slice); +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''point_motion'',%d)',panel); + +%------------------------------- +function cutvessel_buttondown(~) %#ok +%------------------------------- +%Buttondown function for cutting vessels + +myfailed('3D Vessel Cut not yet implemented in 2D view.'); + +%---------------------------------------------- +function centercross_buttondown(panel)%#ok %,measureind) +%---------------------------------------------- +%New buttondown function input is type. All temporary drawing is made using the +%cursor object. + +global DATA + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +DATA.Handles.cursor.Color = 'w'; +DATA.Handles.cursor.Marker = '+'; +DATA.Handles.cursor.MarkerSize = 8; + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +DATA.CursorX = [x,x]; +DATA.CursorY = [y,y]; + +%---------------------------------------------- +function measure_buttondown(panel)%#ok %,measureind) +%---------------------------------------------- +%New buttondown function input is type. The types handled here +%are {Endo,Epi,RVendo,RVepi}. All temporary drawing is made using the +%cursor object. + +global DATA SET + +no = DATA.ViewPanels(panel); + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,x,y); +slices = viewfunctions('slicesinpanel',panel); +scale = viewfunctions('getscale',panel); + +%get montage coordinates of clicked position +[xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice,1)); + +%Set the color of the cursor object which draws the temporary line according to the selected type +DATA.Handles.cursor.Color = 'w'; +DATA.Handles.cursor.Marker = 'o'; +DATA.Handles.cursor.MarkerSize = 5; + +%set parent of the cursor +DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + +%get measure number if new measurenN = nummeasures+1; +[measureind,pointind,measureX,measureY, measureZ] = findfunctions('closestmeasure',panel,x/scale - (xl-1)*SET(no).XSize... + ,y/scale - (yl-1)*SET(no).YSize); + +%If it after the above still is empty create new measure +if isempty(pointind) + measureind = length(SET(no).Measure)+1; + DATA.CursorX = [x,x]; + DATA.CursorY = [y,y]; + DATA.CursorZ = [slice,slice];%clicked slice + pointind = 2; +else %this case handles grabbing of measure point aswell as extend clicking since pointind = number of coordinates + 1 + measureX(pointind) = x/scale; + measureY(pointind) = y/scale; + DATA.CursorY = measureX*scale; %the usual switch for correct rendering + DATA.CursorX = measureY*scale; + DATA.CursorZ = measureZ; +end + +%This way if you click close to a measure you drag that point of the +%measure. +if strcmp(DATA.fig.SelectionType, 'normal') + DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''measure_buttonup'',%d,%d,%d)',panel,measureind,slice); +else + set(DATA.Handles.imageaxes(panel).Children,'ButtonDownFcn',sprintf('buttondownfunctions(''measureadd_buttondown'',%d,%d,%d)',panel,measureind,slice)) + set(DATA.Handles.imageaxes(panel),'ButtonDownFcn',sprintf('buttondownfunctions(''measureadd_buttondown'',%d,%d,%d)',panel,measureind,slice)) +end + +DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''measure_motion'',%d,%d)',panel,pointind); + +%-------------------------------- +function select_buttondown(panel) +%-------------------------------- +%Function that highlights the selected panel if montage also highlight the frame +global DATA SET +% %store the current panel after graphical update and return. The +% %procedure is that first the panel is selected then you can start selecting +% %slices and rois. + +%no = DATA.ViewPanels(panel); + +%orthoview, montage and montage segmented procedure +switch DATA.ViewPanelsType{panel} + case 'one' + %select and update roi + viewfunctions('selectroi',panel); + case {'montage','montagesegmented','montagerow'} + %select and update roi + viewfunctions('selectroi',panel); + [x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + slice = viewfunctions('clickedslice',panel,x,y); + + DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''select_motion'',%d)',panel); + DATA.fig.WindowButtonUpFcn = 'buttonupfunctions(''select_buttonup'')'; + + case {'orth','hla','gla','vla'} + %select and update roi + viewfunctions('selectroi',panel); + [x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + orthoview_buttondown(panel,x,y); + + case {'trans3DP','speedim','sag3DP','cor3DP'} + clicktype = get(DATA.fig,'SelectionType'); + + switch clicktype + case 'normal' + %Normal click + segment3dp.tools('storeclickedposition') + segment3dp.tools('update3DP') + for loop = 1:length(DATA.ViewPanels) + if ~isequal(DATA.ViewPanelsType{loop},'speedim') + drawfunctions('drawtext',loop); + end + end + %set(DATA.fig,'WindowButtonMotionFcn','motionfunctions(''select3dp_motion'')') + %set(DATA.fig,'WindowButtonUpFcn','buttonupfunctions(''buttonup_Callback'')'); + case 'alt' + %Right click => was cut + %Now done by context menu + %if segment3dp.tools('is2d') + % segment3dp.tools('split2d_Callback'); + %else + % segment3dp.tools('split3d_Callback'); + %end + end +end + +if strcmp(DATA.ProgramName, 'Segment') % only executed for segment research version + scale = viewfunctions('getscale',panel); + no = DATA.ViewPanels(panel); + [ystart,xstart] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system + slice = viewfunctions('clickedslice',panel,ystart,xstart); + xl = floor(xstart/scale/SET(no).XSize)*SET(no).XSize; + yl = floor(ystart/scale/SET(no).YSize)*SET(no).YSize; + x = xstart/scale - xl; + y = ystart/scale - yl; + + [type,objectind] = findfunctions('closestobject',panel,x,y,slice); + if strcmp(type, 'Center') + state = viewfunctions('iconson','hideplus'); + if not(state{1}) %not indented + %Set marker color + DATA.Handles.cursor.Color = 'w'; + DATA.Handles.cursor.Marker = '+'; + DATA.CursorX = xl + scale * SET(no).CenterX; + DATA.CursorY = yl + scale * SET(no).CenterY; + %When translating we remove the center point + if ~isempty(SET(no).([type,'X'])) + % set to a very high number so that the original center cross is not + % seen during motion + SET(no).([type,'X']) = 10^6; + SET(no).([type,'Y']) = 10^6; + drawfunctions('drawcentercross',panel) + end + %set parent of the cursor + DATA.Handles.cursor.Parent = DATA.Handles.imageaxes(panel); + DATA.Handles.cursor.YData = DATA.CursorX; + DATA.Handles.cursor.XData = DATA.CursorY; + + DATA.fig.WindowButtonMotionFcn = sprintf('motionfunctions(''translate_motion'',%d,%f,%f)',panel,xstart,ystart); + DATA.fig.WindowButtonUpFcn = sprintf('buttonupfunctions(''translate_buttonup'',%d,''%s'',%d,%f,%f,%d)',panel,type,objectind,xstart,ystart,slice); + end + end +end + +%----------------------------- +function addcalcium_buttondown +%----------------------------- +%buttondown when user clicks at object + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if isempty(SET(no).CT) + return; +end + +if ~isfield(SET(no).CT,'CalciumMask') + return; +end + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(DATA.CurrentPanel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',DATA.CurrentPanel,y,x); + +x = max(min(round(x),SET(no).XSize),1); +y = max(min(round(y),SET(no).YSize),1); +slice = round(slice); + +% +[sx, sy, st, sslice]=size(SET(no).CT.CalciumMask); +calculatedpixelid=[]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y,slice)]; + +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y-1,slice)]; + +binim=SET(no).CT.CalciumMask>0; +binim = squeeze(binim); +bw = bwconncomp(binim); + +for i=1:length(bw.PixelIdxList) + for j=1:length(calculatedpixelid) + if ismember(calculatedpixelid(j),bw.PixelIdxList{1,i})%==1 + rightlist=bw.PixelIdxList{1,i}; + for k=1:length(rightlist) + SET(no).CT.CalciumMask(rightlist(k))=uint8(3); + end + end + end +end +% +%SET(no).CT.CalciumMask(x,y,slice) = uint8(3); + +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); +%Maybe later the bwconn should be precalculated and stored +%im = calcfunctions('calctruedata',SET(no).IM,no); %g?r om till Hounsfieldunits +%outputmask = uint8((im>=130)); +%imbin = (im>=130); %allt ?ver 130 Hu r?knas som kalk +%imbin = squeeze(imbin); +%bw = bwconncomp(imbin); + +%----------------------------- +function addmitralcalcium_buttondown +%----------------------------- +%buttondown when user clicks at object + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if isempty(SET(no).CT) + return; +end + +if ~isfield(SET(no).CT,'CalciumMask') + return; +end + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(DATA.CurrentPanel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',DATA.CurrentPanel,y,x); + +x = max(min(round(x),SET(no).XSize),1); +y = max(min(round(y),SET(no).YSize),1); +slice = round(slice); + +% +[sx, sy, st, sslice]=size(SET(no).CT.CalciumMask); +calculatedpixelid=[]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y,slice)]; + +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y-1,slice)]; + + +binim=SET(no).CT.CalciumMask>0; +binim = squeeze(binim); +bw = bwconncomp(binim); + +for i=1:length(bw.PixelIdxList) + for j=1:length(calculatedpixelid) + if ismember(calculatedpixelid(j),bw.PixelIdxList{1,i})%==1 + rightlist=bw.PixelIdxList{1,i}; + for k=1:length(rightlist) + SET(no).CT.CalciumMask(rightlist(k))=uint8(7); + end + end + end +end +% + +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); + +%----------------------------- +function addaortacalcium_buttondown +%----------------------------- +%buttondown when user clicks at object + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if isempty(SET(no).CT) + return; +end + +if ~isfield(SET(no).CT,'CalciumMask') + return; +end + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(DATA.CurrentPanel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',DATA.CurrentPanel,y,x); + +x = max(min(round(x),SET(no).XSize),1); +y = max(min(round(y),SET(no).YSize),1); +slice = round(slice); + +% +[sx, sy, st, sslice]=size(SET(no).CT.CalciumMask); +calculatedpixelid=[]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y,slice)]; + +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y-1,slice)]; + +binim=SET(no).CT.CalciumMask>0; +binim = squeeze(binim); +bw = bwconncomp(binim); + +for i=1:length(bw.PixelIdxList) + for j=1:length(calculatedpixelid) + if ismember(calculatedpixelid(j),bw.PixelIdxList{1,i})%==1 + rightlist=bw.PixelIdxList{1,i}; + for k=1:length(rightlist) + SET(no).CT.CalciumMask(rightlist(k))=uint8(6); + end + end + end +end +% + +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); + +%----------------------------- +function addcoronarycalcium_buttondown +%----------------------------- +%buttondown when user clicks at object + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if isempty(SET(no).CT) + return; +end + +if ~isfield(SET(no).CT,'CalciumMask') + return; +end + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(DATA.CurrentPanel));%this needs to transformed to the stored coordinate system +slice = viewfunctions('clickedslice',DATA.CurrentPanel,y,x); + +x = max(min(round(x),SET(no).XSize),1); +y = max(min(round(y),SET(no).YSize),1); +slice = round(slice); + +% +[sx, sy, st, sslice]=size(SET(no).CT.CalciumMask); +calculatedpixelid=[]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y,slice)]; + +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x+1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x-1,y-1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y+1,slice)]; +calculatedpixelid= [calculatedpixelid sub2ind(size(squeeze(SET(no).CT.CalciumMask)),x,y-1,slice)]; +binim=SET(no).CT.CalciumMask>0; +binim = squeeze(binim); +bw = bwconncomp(binim); + +for i=1:length(bw.PixelIdxList) + for j=1:length(calculatedpixelid) + if ismember(calculatedpixelid(j),bw.PixelIdxList{1,i})%==1 + rightlist=bw.PixelIdxList{1,i}; + for k=1:length(rightlist) + SET(no).CT.CalciumMask(rightlist(k))=uint8(8); + end + end + end +end +% + +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); + diff --git a/source/buttonupfunctions.m b/source/buttonupfunctions.m new file mode 100644 index 0000000..bff41eb --- /dev/null +++ b/source/buttonupfunctions.m @@ -0,0 +1,1836 @@ +function varargout = buttonupfunctions(varargin) +% Functions for buttonups + +% Broken out by Klas + +%Invoke subfunction + +macro_helper(varargin{:}); %future macro recording use +if (nargout) + [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard +else + feval(varargin{:}); % FEVAL switchyard +end + +%----------------------------------- +function glarotatehandle_Buttonup(panel) %#ok +%----------------------------------- +%Update view according to new rotation +global SET DATA + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +x = x/scale; +y = y/scale; + +glaangle = mod(atan2(SET(no).ResolutionX*(y-SET(no).HLA.slice), ... + SET(no).ResolutionY*(x-SET(no).VLA.slice))+pi/2,pi)-pi/2; +SET(no).GLA.angle = glaangle; + +%also do gla center update this updates the x0 y0 coordinates. Which is +%needed for calculating the plane intersection. +viewfunctions('setglacenter',no); + +set(DATA.fig,'WindowButtonMotionFcn',[], ... + 'WindowButtonUpFcn',[]); + +DATA.Handles.orthoanglehandle.XData = DATA.Handles.cursor.XData(2); +DATA.Handles.orthoanglehandle.YData = DATA.Handles.cursor.YData(2); + +%clear cursor +DATA.Handles.cursor.XData = nan; +DATA.Handles.cursor.YData = nan; +DATA.Handles.cursor.Marker = 'none'; + +%update the ortho panel and the gla panel intersection +drawfunctions('drawplaneintersections'); + +%and gla panel +glapanel = find(strcmp(DATA.ViewPanelsType,'gla')); + +%update gla segmentation intersections +for t = 1:SET(no).TSize + calcfunctions('segmentationintersection_helper',glapanel,t) %this updates stored segmentation intersections for remaining timeframes no graphical update needed. +end + +DATA.ViewIM{glapanel} = []; %forces viewim update of the glapanel +drawfunctions('drawpanel',glapanel); + +%------------------------------ +function crop_buttonup(panel,xstart,ystart,slice) %#ok +%----------------------- +%This function adds the interpolated contour to all timeframes if all +%timeframes mode is selected it also removes motion and buttonupfunction +%settings in DATA.fig + +global DATA SET +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); + +[Xout, Yout] = motionfunctions('crop_motion',panel,xstart,ystart); + +%get translation from montage case +slices = viewfunctions('slicesinpanel',panel); +[xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice)); +xt = (xl-1)*SET(no).YSize*scale; +yt = (yl-1)*SET(no).XSize*scale; + +%this removes any translation from montage and scaling so the format is the +%same as we store coordinates in. +xstart = (xstart-xt)/scale; +ystart = (ystart-yt)/scale; +xlast = (Xout(3)-xt)/scale; +ylast = (Yout(3)-yt)/scale; + +%Get min max points in box and provide to crophelper +yind = max(round([1,min([xlast,xstart])])):min(round([SET(no).YSize,max([xlast,xstart])])); +xind = max(round([1,min([ylast,ystart])])):min(round([SET(no).XSize,max([ylast,ystart])])); + +%remove buttonup and motionfunctions +buttonup_Callback + +if ~yesno('Apply crop?',[],DATA.GUI.Segment) + %reset cursor + DATA.Handles.cursor.XData = nan; + DATA.Handles.cursor.YData = nan; + return; +end + +%reset cursor +DATA.Handles.cursor.XData = nan; +DATA.Handles.cursor.YData = nan; + +tools('crophelper',no,xind,yind); %after this we are done + +tools('disableundo') +DATA.ViewIM{DATA.CurrentPanel}=[]; +drawfunctions('drawno',no) +drawfunctions('drawselectedframe',panel) + +%also update thumbnail! +drawfunctions('drawthumbnails',1,0) + +%------------------------------ +function interp_buttonup(panel,type,slice) %#ok +%----------------------- +%This function adds the interpolated contour to all timeframes if all +%timeframes mode is selected it also removes motion and buttonupfunction +%settings in DATA.fig + +global DATA SET +no = DATA.ViewPanels(panel); +ctf = SET(no).CurrentTimeFrame; + +%If straintagging initiated adjust LVupdated +if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') + SET(no).StrainTagging.LVupdated = 1; +end + +%This applies the contours and interpolation points to all timeframes +if not(DATA.ThisFrameOnly) %findindented(DATA.Handles.hideiconholder,'allframesmode') + %all frames mode + for tf = 1:SET(no).TSize + SET(no).([type(1:end-6),'X'])(:,tf,slice)=SET(no).([type(1:end-6),'X'])(:,ctf,slice); + SET(no).([type(1:end-6),'Y'])(:,tf,slice)=SET(no).([type(1:end-6),'Y'])(:,ctf,slice); + SET(no).([type,'X']){tf,slice} = SET(no).([type,'X']){ctf,slice}; + SET(no).([type,'Y']){tf,slice} = SET(no).([type,'Y']){ctf,slice}; + end +end + +buttonup_Callback +if SET(no).([type(1:end-6),'InterpOngoing']) + drawfunctions('drawinterp',panel,type); +else + drawfunctions('drawno',no); +end + +calcfunctions('updatemarandscar',no); + +%update result panel +switch type + case {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'} + if ~SET(no).([type(1:end-6),'InterpOngoing']) + segment('updatevolume') + end +end + +%------------------------------ +function scale_buttonup(panel,type,objectind,slice,startrad) %#ok +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + magno = SET(no).Flow.MagnitudeNo; +else + magno = no; +end +scale = viewfunctions('getscale',panel); + +xc = mean(DATA.CursorX); +yc = mean(DATA.CursorY); + +xl = floor(xc/scale/SET(no).XSize)*SET(no).XSize; +yl = floor(yc/scale/SET(no).YSize)*SET(no).YSize; + +%Update cursor coordinates then right back into SET struct +[DATA.CursorX,DATA.CursorY, scalevalue] = motionfunctions('scale_motion',panel,startrad); +switch type + case {'Endo','Epi'} +% %objectind is not used for contours +% if DATA.ThisFrameOnly %findindented(DATA.Handles.hideiconholder,'allframesmode') +% %all frames mode +% % SET(no).([type,'X'])(:,:,slice) = ... +% % repmat(DATA.CursorX/scale - xl,[1,SET(no).TSize]); +% % SET(no).([type,'Y'])(:,:,slice) = ... +% % repmat(DATA.CursorY/scale - yl,[1,SET(no).TSize]); +% tf = SET(no).CurrentTimeFrame; +% else +% % SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice) = ... +% % DATA.CursorX/scale - xl; +% % SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice) = ... +% % DATA.CursorY/scale - yl; +% tf = 1:SET(magno).TSize; +% end + stepsize = (scalevalue-1)/0.02; + lv('segmentexpandcontract_Callback',stepsize,lower(type),slice); + + %If straintagging initiated adjust LVupdated + if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') + SET(no).StrainTagging.LVupdated = 1; + end + calcfunctions('updatemarandscar',no); + case {'RVEndo','RVEpi'} + stepsize = (scalevalue-1)/0.02; + rv('expandcontract_Callback',stepsize,lower(type),slice); + + case 'Roi' + if DATA.ThisFrameOnly %not(findindented(DATA.Handles.hideiconholder,'allframesmode')) + %single frame mode + DATA.DoThisFrameOnly = true; %flag for calc functions + SET(magno).Roi(objectind).X(:,SET(no).CurrentTimeFrame) = DATA.CursorX/scale - xl; + SET(magno).Roi(objectind).Y(:,SET(no).CurrentTimeFrame) = DATA.CursorY/scale - yl; + else + tf = 1:SET(magno).TSize; + mx = repmat(mean(SET(magno).Roi(SET(magno).RoiCurrent).X(:,tf)),size(SET(magno).Roi(SET(magno).RoiCurrent),1),1); + my = repmat(mean(SET(magno).Roi(SET(magno).RoiCurrent).Y(:,tf)),size(SET(magno).Roi(SET(magno).RoiCurrent),1),1); + SET(magno).Roi(objectind).X(:,tf) = bsxfun(@plus,mx,scalevalue*bsxfun(@minus,SET(magno).Roi(SET(magno).RoiCurrent).X(:,tf),mx)); + SET(magno).Roi(objectind).Y(:,tf) = bsxfun(@plus,my,scalevalue*bsxfun(@minus,SET(magno).Roi(SET(magno).RoiCurrent).Y(:,tf),my)); +% SET(magno).Roi(objectind).X = repmat(DATA.CursorX/scale - xl,[1,SET(no).TSize]); +% SET(magno).Roi(objectind).Y = repmat(DATA.CursorY/scale - yl,[1,SET(no).TSize]); + end + %KG: update Area and Mean of the ROI + [~,SET(magno).Roi(objectind).Area] = ... + calcfunctions('calcroiarea',magno,objectind); + [m,sd]=calcfunctions('calcroiintensity',magno,objectind); + SET(magno).Roi(objectind).Mean = m; + SET(magno).Roi(objectind).StD = sd; + %KG: update flowpanel, and flowresult, for FLOW ROI + if isfield(SET(magno).Roi(objectind), 'FlowSnake') + segment('updateflow'); + end + DATA.DoThisFrameOnly = false; %flag for calc functions +end + +drawfunctions('drawno',no) + +DATA.Handles.cursor.YData = nan; +DATA.Handles.cursor.XData = nan; +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; + +%---------------------------------------------- +function contrast_buttonup(panel,slice,xstart,ystart,xsize,ysize) +%---------------------------------------------- +global DATA SET +no = DATA.ViewPanels(panel); +[contrast,brightness] = motionfunctions('contrast_motion',panel,slice,xstart,ystart,xsize,ysize); +SET(no).IntensityMapping.Contrast = contrast; +SET(no).IntensityMapping.Brightness = brightness; +DATA.ViewIM{panel} = []; +drawfunctions('drawimages',panel); + +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; + +%------------------------------ +function translate_buttonup(panel,type,objectind,xstart,ystart,slice) %#ok +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + magno = SET(no).Flow.MagnitudeNo; +else + magno = no; +end +scale = viewfunctions('getscale',panel); +xl = floor(xstart/scale/SET(no).XSize)*SET(no).XSize; +yl = floor(ystart/scale/SET(no).YSize)*SET(no).YSize; + +%Update cursor coordinates then right back into SET struct +[DATA.CursorX,DATA.CursorY] = motionfunctions('translate_motion',panel,xstart,ystart); + +x = DATA.CursorX/scale - xl; +y = DATA.CursorY/scale - yl; + +%check if any part of the contour is out of bounds then place it along the +%edge of the image. +x = min(x,SET(no).XSize-2); +x = max(x,2); + +y = min(y,SET(no).YSize-2); +y = max(y,2); + +switch type + case {'Endo','Epi','RVEndo','RVEpi'} + %objectind is not used for contours + if not(DATA.ThisFrameOnly) %findindented(DATA.Handles.hideiconholder,'allframesmode') + %all frames mode + diffx = SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice) - DATA.CursorX/scale + xl; + diffy = SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice) - DATA.CursorY/scale + yl; + + newx = SET(no).([type,'X'])(:,:,slice) - diffx; + newx = min(newx,SET(no).XSize-2); + newx = max(newx,2); + newy = SET(no).([type,'Y'])(:,:,slice) - diffy; + + newy = min(newy,SET(no).YSize-2); + newy = max(newy,2); + SET(no).([type,'X'])(:,:,slice) = newx;% repmat(x,[1,SET(no).TSize]); + SET(no).([type,'Y'])(:,:,slice) = newy;% repmat(y,[1,SET(no).TSize]); + else + SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice) = x; + SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice) = y; + end + + %If straintagging initiated adjust LVupdated + if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') + SET(no).StrainTagging.LVupdated = 1; + end + calcfunctions('updatemarandscar',no); + %update volumes in case of cropped by border + segment('updatevolume') + + case 'Roi' + if DATA.ThisFrameOnly %~findindented(DATA.Handles.hideiconholder,'allframesmode') + %single frame mode + DATA.DoThisFrameOnly = true; %flag for calc functions + SET(magno).Roi(objectind).X(:,SET(no).CurrentTimeFrame) = x; + SET(magno).Roi(objectind).Y(:,SET(no).CurrentTimeFrame) = y; + else + diffx = SET(magno).Roi(objectind).X(:,SET(no).CurrentTimeFrame) - DATA.CursorX/scale + xl; + diffy = SET(magno).Roi(objectind).Y(:,SET(no).CurrentTimeFrame) - DATA.CursorY/scale + yl; + newx = SET(magno).Roi(objectind).X - diffx; + newx = min(newx,SET(no).XSize-2); + newx = max(newx,2); + newy = SET(magno).Roi(objectind).Y - diffy; + + newy = min(newy,SET(no).YSize-2); + newy = max(newy,2); + SET(magno).Roi(objectind).X = newx;%repmat(x,[1,SET(no).TSize]); + SET(magno).Roi(objectind).Y = newy;%repmat(y,[1,SET(no).TSize]); + end + + %update mean area std in case of cropped by border + [~,SET(magno).Roi(objectind).Area] = ... + calcfunctions('calcroiarea',magno,objectind); + [m,sd]=calcfunctions('calcroiintensity',magno,objectind); + SET(magno).Roi(objectind).Mean = m; + SET(magno).Roi(objectind).StD = sd; + + case 'Measure' + measurex = x; + measurey = y; + switch DATA.ViewPanelsType{panel} + case 'hla' + SET(no).Measure(objectind).X = ones(size(measurey))*SET(no).HLA.slice; + SET(no).Measure(objectind).Y = measurey; + SET(no).Measure(objectind).Z = measurex; + case 'vla' + SET(no).Measure(objectind).X = measurey; + SET(no).Measure(objectind).Y = ones(size(measurey))*SET(no).VLA.slice; + SET(no).Measure(objectind).Z = measurex; + case 'gla' + [SET(no).Measure(objectind).X,SET(no).Measure(measureN).Y,... + SET(no).Measure(objectind).Z] = calcfunctions('gla2sax',measurex,measurey,no); + otherwise + SET(no).Measure(objectind).X = measurex; + SET(no).Measure(objectind).Y = measurey; + SET(no).Measure(objectind).Z = ones(size(measurey))*SET(no).CurrentSlice; + end + %Calc length in case of cropped by border + L = sum(sqrt(... + (SET(no).ResolutionX*diff(measurex)).^2+... + (SET(no).ResolutionY*diff(measurey)).^2+... + ((SET(no).SliceThickness+SET(no).SliceGap)*diff(SET(no).Measure(objectind).Z)).^2)); + + SET(no).Measure(objectind).Length = L; + + case 'Point' + SET(no).Point.X(objectind) = x; + SET(no).Point.Y(objectind) = y; + case 'Center' + SET(no).CenterX = x; + SET(no).CenterY = y; +end + +%draw changes +drawfunctions('drawno',no) + +%update result panel +switch type + case {'Endo','Epi','RVEndo','RVEpi'} + segment('updatevolume'); + case 'Roi' + segment('updateflow'); + DATA.DoThisFrameOnly = false; %flag for calc functions + otherwise + segment('updatemeasurement'); +end + +DATA.Handles.cursor.YData = nan; +DATA.Handles.cursor.XData = nan; + +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; + + +%------------------------------ +function translateall_buttonup(panel,xstart,ystart,slice) %#ok +%----------------------- +global DATA SET + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); + +%translate the contours by xstart-x transferred to SET contour domain. +tx = (xstart-x)/scale; +ty = (ystart-y)/scale; + + + +types = {'Endo','Epi','RVEndo','RVEpi'}; + +for i = 1:length(types) + type = types{i}; + if ~isempty(SET(no).([type,'X'])) && ~all(isnan(SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice))) + contourx = SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice)-tx; + contoury = SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice)-ty; + + %check if any part of the contour is out of bounds then place it along the + %edge of the image. + contourx = min(contourx,SET(no).XSize-2); + contourx = max(contourx,2); + contoury = min(contoury,SET(no).YSize-2); + contoury = max(contoury,2); + + SET(no).([type,'X'])(:,SET(no).CurrentTimeFrame,slice) = contourx; + SET(no).([type,'Y'])(:,SET(no).CurrentTimeFrame,slice) = contoury; + end +end + +%If straintagging initiated adjust LVupdated +if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') + SET(no).StrainTagging.LVupdated = 1; +end +calcfunctions('updatemarandscar',no); +drawfunctions('drawno',no) + +DATA.CursorX = []; +DATA.CursorY = []; +DATA.Handles.cursor.YData = nan; +DATA.Handles.cursor.XData = nan; + +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; + +%---------------------------------------------- +function point_buttonup(panel,pointind,slice) %#ok +%---------------------------------------------- +%Point button up function. Has the current panel and index of the +%dragged point we are updating as input. + +global DATA SET + +if nargin == 2 + slice = []; +end + +no = DATA.ViewPanels(panel); +%Restore/Kill all action functions +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +%check if placed in 3dp view then we need to store it in a different way +if any(strcmp(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','speedim','cor3DP'})) + + [xsz,ysz,~,~] = segment3dp.tools('viewsizeandres',SET(no).LevelSet.Pen.Color,no); + + px = min(x,xsz-2); + px = max(px,2); + py = min(y,ysz-2); + py = max(py,2); + + [r,g,b] = segment3dp.tools('xy2rgb',SET(no).LevelSet.Pen.Color,px,py); + [x,y,z] = segment3dp.tools('rgb2xyz',r,g,b); + + segment3dp.tools('addpoint_helper',x,y,z,no) + + if segment3dp.isviewportalive + segment3dp.tools('addpointstoviewport'); %updates all points + end + + %Indent show icon + DATA.Handles.configiconholder.indent('showpoint',1); + + for p = 1:length(DATA.ViewPanels) + if ~isequal(DATA.ViewPanelsType{p},'viewport') + viewfunctions('updatedrawlist',p) + drawfunctions('drawpanel',p) + end + end + +else + %Not 3DP + slices = viewfunctions('slicesinpanel',panel); + scale = viewfunctions('getscale',panel); + %get montage coordinates of clicked position + [yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice)); + xt = (xl-1)*SET(no).XSize*scale; + yt = (yl-1)*SET(no).YSize*scale; + + %this removes any translation from montage and scaling so the format is the + %same as we store coordinates in. + px = (x-xt)/scale; + py = (y-yt)/scale; + + %check if any part of the contour is out of bounds then place it along the + %edge of the image. + px = min(px,SET(no).XSize-2); + px = max(px,2); + + py = min(py,SET(no).YSize-2); + py = max(py,2); + + SET(no).Point.X(pointind) = px; + SET(no).Point.Y(pointind) = py; + SET(no).Point.Z(pointind) = slice; + if length(SET(no).Point.Label) +%---------------------------------------------- +%Measure button up function. Has the current panel index of the currently +%dragged point and finally the index of the measure we are updating as +%input. + +global DATA SET + +no = DATA.ViewPanels(panel); +%Restore/Kill all action functions +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; + +%get the slice and normalize the coordinates +scale = viewfunctions('getscale',panel); + +slices = viewfunctions('slicesinpanel',panel); + +%get montage coordinates of clicked position +[xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice,1)); +if isempty(xl) + xl = 1; + yl = 1; +end +measurey = DATA.CursorX/scale-(xl-1)*SET(no).YSize; +measurex = DATA.CursorY/scale-(yl-1)*SET(no).XSize; + +%check if any part of the contour is out of bounds then place it along the +%edge of the image. +measurex = min(measurex,SET(no).XSize-2); +measurex = max(measurex,2); + +measurey = min(measurey,SET(no).YSize-2); +measurey = max(measurey,2); + +switch DATA.ViewPanelsType{panel} + case 'hla' + SET(no).Measure(measureN).X = ones(size(measurey))*SET(no).HLA.slice; + SET(no).Measure(measureN).Y = measurey; + SET(no).Measure(measureN).Z = measurex; + case 'vla' + SET(no).Measure(measureN).X = measurey; + SET(no).Measure(measureN).Y = ones(size(measurey))*SET(no).VLA.slice; + SET(no).Measure(measureN).Z = measurex; + case 'gla' + [SET(no).Measure(measureN).X,SET(no).Measure(measureN).Y,... + SET(no).Measure(measureN).Z] = calcfunctions('gla2sax',measurex,measurey,no); + otherwise + SET(no).Measure(measureN).X = measurex; + SET(no).Measure(measureN).Y = measurey; + SET(no).Measure(measureN).Z = DATA.CursorZ;%ones(size(measurey))*SET(no).CurrentSlice; +end + +%Calc length +L = sum(sqrt(... + (SET(no).ResolutionX*diff(measurex)).^2+... + (SET(no).ResolutionY*diff(measurey)).^2+... + ((SET(no).SliceThickness+SET(no).SliceGap)*diff(SET(no).Measure(measureN).Z)).^2)); + +SET(no).Measure(measureN).Length = L; +SET(no).Measure(measureN).Name = []; +SET(no).Measure(measureN).T = SET(no).CurrentTimeFrame; +SET(no).Measure(measureN).LongName = []; + +DATA.Handles.cursor.XData = nan; +DATA.Handles.cursor.YData = nan; +DATA.CursorX = []; +DATA.CursorY = []; +DATA.CursorZ = []; + +%Remove markers from cursor object +DATA.Handles.cursor.Marker = 'none'; + +if any(strcmp(DATA.ViewPanelsType{panel},{'orth','hla','gla','vla'})) + for p = 1:length(DATA.ViewPanels) + drawfunctions('drawmeasures',p) + end +else + drawfunctions('drawmeasures',panel) +end + +buttondownfunctions('updatebuttondowns','Measure'); +viewfunctions('updatedrawlist',panel); +drawfunctions('drawpanel',panel); +segment('updatemeasurement'); + + +%------------------------------------------------------------------------ +function select_buttonup +%------------------------------------------------------------------------ +%Function that highlights the selected panel if montage also highlight the frame +global DATA + +DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; +DATA.fig.WindowButtonUpFcn = ''; +drawfunctions('drawplaneintersections') + + +%---------------------------------------------- +function balloon_buttonup(panel,type,slice,tf) %#ok +%---------------------------------------------- +%Generic buttonup that only clears motion and buttonup function in fig. +global DATA SET + +no = DATA.ViewPanels(panel); + +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + no = SET(no).Flow.MagnitudeNo; +end + +y = DATA.CursorX; +x = DATA.CursorY; + +if isempty(x) + DATA.Handles.cursor.XData = nan; + DATA.Handles.cursor.YData = nan; + DATA.CursorX = []; + DATA.CursorY = []; + + DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; + DATA.fig.WindowButtonUpFcn = ''; + return +end + +%Determine which slice we are drawing in and interpolation mode to translate the cursor contour . +scale = viewfunctions('getscale',panel); +slices = viewfunctions('slicesinpanel',panel); +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice)); +xt = (xl-1)*SET(no).XSize*scale; +yt = (yl-1)*SET(no).YSize*scale; +%this removes any translation from montage and scaling so the format is the +%same as we store coordinates in. +x = (x-xt)/scale; +y = (y-yt)/scale; + +%Adjust curve direction. +[x,y]=mypoly2cw(x,y); + +switch type + case 'Roi' + %we do not merge rois + x_comp = []; + y_comp = []; + otherwise + if ~isempty(SET(no).([type,'X'])) + x_comp = SET(no).([type,'X'])(:,tf,slice); + y_comp = SET(no).([type,'Y'])(:,tf,slice); + else + x_comp = []; + y_comp = []; + end +end + + +%this will trigger if exists segmentation in slice and timeframe +if ~isempty(x_comp) && ~all(isnan(x_comp)) + %determine if polygon is inside other polygon. If all is inside we keep the + % new contour. + mnew = poly2mask(x,y,SET(no).XSize,SET(no).YSize); + mold = poly2mask(x_comp,y_comp,SET(no).XSize,SET(no).YSize); + + %this means that there is overlap between the old balloon and the new and an addition in the new blob that we need to + %incorporate + if any(mnew(:).*mold(:)>0) && any(mnew(:)-mold(:)>0) + m = mold+mnew>0; + [mi,mj] = ind2sub(size(m),find(m,1)); + X = bwtraceboundary(m,[mi,mj],'W'); + + xm = zeros(length(X),1); + ym = zeros(length(X),1); + + %idea is to find the closest point of all points which are not + %inside a polygon + [in1,~] = inpolygon(x,y,x_comp,y_comp); + [in2,~] = inpolygon(x_comp,y_comp,x,y); + x_cat = cat(1,x(~in1),x_comp(~in2)); + y_cat = cat(1,y(~in1),y_comp(~in2)); + + %find the closest points on the combined polygon of the contour and + %the drawn. Then let resamplecurve work removing any duplicates. + for i = 1:length(X) + [~,ind] = min((X(i,2)-x_cat).^2+(X(i,1)-y_cat).^2); + xm(i) = x_cat(ind); + ym(i) = y_cat(ind); + end + x = xm; + y = ym; + end +end + +%This might fail for fast clicks where xy contains duplicates or is empty. +%if so clear the cursor object and motion buttonupfunctions and return before writing anything back to SET. +try + %removes duplicate points and resamples the contour + [x,y] = calcfunctions('resamplecurve',x,y,DATA.NumPoints-1); + + %Close the contour + x = [x,x(1)]; + y = [y,y(1)]; + +catch + DATA.Handles.cursor.XData = nan; + DATA.Handles.cursor.YData = nan; + DATA.CursorX = []; + DATA.CursorY = []; + DATA.Handles.cursor.LineStyle = '-'; + + DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; + DATA.fig.WindowButtonUpFcn = ''; + return +end + +switch type + case 'Roi' + %For the balloon case the we always create a new Roi + emptyroiinds = find(cellfun(@isempty,{SET(no).Roi.X})); + if ~isempty(emptyroiinds) + roiind = emptyroiinds(1); + else + roiind =length(SET(no).Roi)+1; + end + + if not(DATA.ThisFrameOnly) %findindented(DATA.Handles.hideiconholder,'allframesmode') + %all frames mode + SET(no).Roi(roiind).X = repmat(x',[1,SET(no).TSize]); + SET(no).Roi(roiind).Y = repmat(y',[1,SET(no).TSize]); + else + DATA.DoThisFrameOnly = true; %flag for calc functions + tmpx = nan(length(x),SET(no).TSize); + tmpy = nan(length(x),SET(no).TSize); + tmpx(:,tf) = x; + tmpy(:,tf) = y; + SET(no).Roi(roiind).X = tmpx; + SET(no).Roi(roiind).Y = tmpy; + end + + SET(no).Roi(roiind).T = 1:SET(no).TSize; + SET(no).Roi(roiind).Z = slice; + + %Set roicurrent + SET(no).RoiCurrent = roiind; + + %Increase number of rois + SET(no).RoiN = SET(no).RoiN + 1; + + %Update roi name + + SET(no).Roi(roiind).Sign = 1; + SET(no).Roi(roiind).Name = sprintf('ROI-%d',SET(no).RoiN); + newlinecolor = roi('roisetcolorbasedonposition',no); + SET(no).Roi(roiind).LineSpec = [newlinecolor,'-']; + + %Calculate area and intensity of ROI + [~,SET(no).Roi(roiind).Area] = ... + calcfunctions('calcroiarea',no,roiind); + [m,sd]=calcfunctions('calcroiintensity',no,roiind); + SET(no).Roi(roiind).Mean = m; + SET(no).Roi(roiind).StD = sd; + + %Update result panel + segment('updateflow'); + DATA.DoThisFrameOnly = false; %flag for calc functions + + otherwise + + if strcmp(type, 'RVEndo') + [x,y] = calcfunctions('calcpointsoutsideLV',x,y,no); + end + + if isempty(SET(no).([type,'X'])) + SET(no).([type,'Y']) = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + SET(no).([type,'X']) = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + end + + if not(DATA.ThisFrameOnly) %findindented(DATA.Handles.hideiconholder,'allframesmode') + %all frames mode + SET(no).([type,'Y'])(:,:,slice)=repmat(y',[1,SET(no).TSize]); + SET(no).([type,'X'])(:,:,slice)=repmat(x',[1,SET(no).TSize]); + else + SET(no).([type,'Y'])(:,tf,slice)=y; + SET(no).([type,'X'])(:,tf,slice)=x; + end + %If straintagging initiated adjust LVupdated + if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') + SET(no).StrainTagging.LVupdated = 1; + end + calcfunctions('updatemarandscar',no); + segment('updatevolume') +end + +% %generate image from normals of the endo contour +% x = SET(no).([type,'Y'])(:,tf,slice); +% y = SET(no).([type,'X'])(:,tf,slice); +% +% %use 100 points +% [x,y] = calcfunctions('resamplecurve',x,y,150);%round(DATA.NumPoints/2)); +% x = x'; +% y = y'; +% +% dy = conv([x(end-1);x],[1 0 -1]/2,'valid');%diff(SET(no).([type,'Y'])(:,tf,slice),); +% dx = conv([y(end-1);y],[1 0 -1]/2,'valid');%diff(SET(no).([type,'X'])(:,tf,slice)); +% +% %get normals +% normals = -[0 -1 ; 1 0]*[dx,dy]'./sqrt(dx.*dx+dy.*dy)'; +% X = [y(1:end-1),x(1:end-1)]'; +% %extract lines from along normals in image +% A = linspace(0,40,200); +% lines =X + normals.*reshape(repmat(A,2,1),2,1,200); +% +% imA = zeros(size(lines,2),size(lines,3)); +% +% %image we retrieve values from +% imq = histeq(SET(no).IM(:,:,tf,slice),100); +% +% for i =1:size(lines,2) +% xinds = round(squeeze(lines(1,i,:))); +% yinds = round(squeeze(lines(2,i,:))); +% inds = xinds>0 & xinds<=SET(no).YSize & yinds>0 & yinds<=SET(no).XSize; +% xinds = xinds(inds); +% yinds = yinds(inds); +% indq = sub2ind(size(imq),xinds,yinds); +% imA(i,inds) = imq(indq); +% end +% +% %we can bin the bloodpool content and fit a gaussian to this which we draw +% %the content of imA from. +% padim = padarray(imA,[2,2],'replicate'); +% A = conv2(padim,ones(5)/25,'valid'); +% +% %alternative idea +% %[~,medmed] = max(abs(diff(mean(A)))); +% %medianres = ones(1,size(lines,2))*medmed; +% +% sample = A(:,1:6); +% mu = mean2(sample); +% sigma = std(sample(:)); +% y = normpdf(A(:),mu,sigma); +% draw_imA = reshape(y,size(imA)); +% level = graythresh(draw_imA); +% +% %multithresh +% %levels = multithresh(draw_imA,2); +% %a = single(draw_imA>levels(1) & draw_imAlevel); +% a(a==0) = -inf; +% t = cumsum(a,2); +% +% %take the local median or less around a row intervall +% medianres = max(t,[],2); +% +% medianres(isinf(medianres)) = nan; +% %medianres = medfilt1(maxvals,5); +% medmed = round(nanmedian(medianres)); +% +% %just apply median for all +% medianres(:) = medmed; +% +% if isempty(SET(no).EpiX) +% SET(no).EpiY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% SET(no).EpiX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% end +% +% %apply this median index as the number of steps along the normal of the endo contour +% tmpy = zeros(1,size(lines,2)); +% tmpx = zeros(1,size(lines,2)); +% +% for i = 1:size(lines,2) +% tmpy(i)=lines(2,i,medianres(i)); +% tmpx(i)=lines(1,i,medianres(i)); +% end +% +% %apply this median index as the number of steps along the normal of the endo contour +% [x,y] = calcfunctions('resamplecurve',tmpx',tmpy',DATA.NumPoints-1); +% +% %Close the contour +% x = [x,x(1)]; +% y = [y,y(1)]; +% +% SET(no).EpiY(:,tf,slice)=y; +% SET(no).EpiX(:,tf,slice)=x; +% +% %do refine then smooth twice +% %epismoothsegmentation_helper(no,tf,slice) +% %lvpeter('segmentrefineepi_Callback') +% %epismoothsegmentation_helper(no,tf,slice) +% + +% figure; plot(SET(no).EpiY(:,tf,slice),SET(no).EpiX(:,tf,slice),'g') +% hold on +% plot(SET(no).EndoY(:,tf,slice),SET(no).EndoX(:,tf,slice),'r') +% find +% figure; imagesc(draw_imA +%---------------------------------------------- +global DATA SET +panelslinked = find(ismember(DATA.ViewPanels,SET(DATA.ViewPanels(panel)).Linked)); +for actpanel = panelslinked + no = DATA.ViewPanels(actpanel); + + %Update text position and show text again + viewfunctions('updatetextposition',actpanel) + scale = viewfunctions('getscale',actpanel); + + switch DATA.ViewPanelsType{actpanel} + case 'trans3DP' + SET(no).LevelSet.View.RZoomState(1:2) = DATA.Handles.imageaxes(actpanel).XLim/scale; + SET(no).LevelSet.View.RZoomState(3:4) = DATA.Handles.imageaxes(actpanel).YLim/scale; + case 'sag3DP' + SET(no).LevelSet.View.GZoomState(1:2) = DATA.Handles.imageaxes(actpanel).XLim/scale; + SET(no).LevelSet.View.GZoomState(3:4) = DATA.Handles.imageaxes(actpanel).YLim/scale; + case 'cor3DP' + SET(no).LevelSet.View.BZoomState(1:2) = DATA.Handles.imageaxes(actpanel).XLim/scale; + SET(no).LevelSet.View.BZoomState(3:4) = DATA.Handles.imageaxes(actpanel).YLim/scale; + otherwise + %update the normalzoomstate field + SET(no).NormalZoomState(1:2) = DATA.Handles.imageaxes(panel).XLim/scale; + SET(no).NormalZoomState(3:4) = DATA.Handles.imageaxes(panel).YLim/scale; + end + + %Draw all existing texts by calling drawpanel + drawfunctions('drawpanel',actpanel) +end + +buttonup_Callback + +%---------------------------------------------- +function pen_buttonup(panel,type,slice,tf,doall) %#ok +%---------------------------------------------- +%New button up function input is type and panel. The types handled here +%are {Endo,Epi,RVendo,RVepi,Roi}. +global DATA SET + +no = DATA.ViewPanels(panel); + +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + no = SET(no).Flow.MagnitudeNo; +end + +if nargin<4 + tf = SET(no).CurrentTimeFrame; +end + +if nargin<5 + doall = 0; +end + +if nargin < 3 + slice = SET(no).CurrentSlice; +end + +y = DATA.CursorX; +x = DATA.CursorY; + +if isempty(x) || ismember(DATA.ViewPanelsType(panel),{'hla','vla','gla'}) + DATA.Handles.cursor.XData = nan; + DATA.Handles.cursor.YData = nan; + DATA.CursorX = []; + DATA.CursorY = []; + + DATA.fig.WindowButtonMotionFcn = 'segment(''toggleplaceholdermotion'')'; + DATA.fig.WindowButtonUpFcn = ''; + return +end + +%Adjust curve direction. +[x,y]=mypoly2cw(x,y); + +%Determine which slice we are drawing in and interpolation mode to translate the cursor contour . +scale = viewfunctions('getscale',panel); +slices = viewfunctions('slicesinpanel',panel); +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices==slice)); +xt = (xl-1)*SET(no).XSize*scale; +yt = (yl-1)*SET(no).YSize*scale; + +%this removes any translation from montage and scaling so the format is the +%same as we store coordinates in. +x = (x-xt)/scale; +y = (y-yt)/scale; + +%check if any part of the contour is out of bounds then place it along the +%edge of the image. +x = min(x,SET(no).XSize-2); +x = max(x,2); + +y = min(y,SET(no).YSize-2); +y = max(y,2); + + +%two possibilities, either the segmentation overwrites the entire contour +%field in the SET struct or it is appended to it. this is determined by +%checking if it is closer to the startpoint of the drawing or the closest +%point on the contour. As the orientation of the contour is adjusted so +%both have a counterclockwise orientation we only need to handle two cases if we are going to append. +%These cases are if the start index of the prior is removed in the append +%or not. We set up both these cases and evaluate the two potential closed +%curves and then choose the one which constitutes the largest area. +switch type + case {'Scar','MaR','MO','ScarRubber','MaRRubber','CalciumPen', 'CalciumPenRemove', 'CalciumPenBlue', 'CalciumPenRed', 'CalciumPenLilac'} + %This will trigger new contour case + x_close = []; + y_close = []; + startdist = inf; + enddist = inf; + drawdist = 0; + + case 'Roi' + if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + [startdist,roiind1,ind1] = findfunctions('closestroi',panel,x(1),y(1),[],[],no); + [enddist,roiind2,ind2] = findfunctions('closestroi',panel,x(end),y(end),[],[],no); + else + [startdist,roiind1,ind1] = findfunctions('closestroi',panel,x(1),y(1)); + [enddist,roiind2,ind2] = findfunctions('closestroi',panel,x(end),y(end)); + end + drawdist = sqrt((x(1)-x(end)).^2+(y(1)-y(end)).^2); + + [~,closest] = min([startdist,enddist,drawdist]); + switch closest + case 1 %the starting point has a roi that is very close + x_close = SET(no).Roi(roiind1).X(:,tf); + y_close = SET(no).Roi(roiind1).Y(:,tf); + newroi = false; + roiind = roiind1; + case 2 %the end point has a roi that is very close + x_close = SET(no).Roi(roiind2).X(:,tf); + y_close = SET(no).Roi(roiind2).Y(:,tf); + newroi = false; + roiind = roiind2; + case 3 %the starting point is closest to the endpoint of the roi. + x_close = []; + y_close = []; + newroi = true; + emptyroiinds = find(cellfun(@isempty,{SET(no).Roi.X})); + if ~isempty(emptyroiinds) + roiind = emptyroiinds(1); + else + roiind =length(SET(no).Roi)+1; + end + end + otherwise + if ~isempty(SET(no).([type,'X'])) && ... + ~all(isnan(SET(no).([type,'X'])(:,tf,slice))) + + x_close = SET(no).([type,'X'])(:,tf,slice); + y_close = SET(no).([type,'Y'])(:,tf,slice); + + %distance to and index of closestcontour point from drawing startpoint + [startdist,ind1] = min((y_close-y(1)).^2+... + (x_close-x(1)).^2); + + %distance to and index of closestcontour point from drawing endpoint + [enddist,ind2] = min((y_close-y(end)).^2+... + (x_close-x(end)).^2); + + %distance between drawing start and endpoint + drawdist = (y(1)-y(end)).^2+... + (x(1)-x(end)).^2; + else + %This will trigger new contour case + x_close = []; + y_close = []; + startdist = inf; + enddist = inf; + drawdist = 0; + end +end + +if isrow(x_close) + x_close = x_close'; + y_close = y_close'; +end + +%this is the new contour decision +if drawdist +%----------------------------- +%Button up function for fastmarch tool. + +global DATA SET NO + +set(DATA.fig,'WindowButtonMotionFcn',@DATA.toggleplaceholdermotion); +set(DATA.fig,'WindowButtonUpFcn',''); + +%If we are still calculating arrivaltimes then we return after clearing the +%motion and buttonupfunctions. +if DATA.Run + return +end + +segment3dp.tools('storeclickedposition'); + +[x,y,z] = segment3dp.tools('rgb2xyz',SET(NO).LevelSet.View.RSlice,SET(NO).LevelSet.View.GSlice, SET(NO).LevelSet.View.BSlice); +arrivaltime = DATA.LevelSet.ArrivalTime(x,y,z); + +if isnan(arrivaltime) + arrivaltime = max(DATA.LevelSet.ArrivalTime(:)); +end + +%normal code +SET(NO).LevelSet.BW(DATA.LevelSet.ArrivalTime < arrivaltime) = uint8(255); + +%--- code to make the outer nicer + +%Extract subvolume +box = segment3dp.tools('findboundingbox',DATA.LevelSet.ArrivalTime < arrivaltime,2); %0=margin +bw = SET(NO).LevelSet.BW(box.xmin:box.xmax,box.ymin:box.ymax,box.zmin:box.zmax); +A = DATA.LevelSet.ArrivalTime(box.xmin:box.xmax,box.ymin:box.ymax,box.zmin:box.zmax); +S = SET(NO).LevelSet.SpeedIM(box.xmin:box.xmax,box.ymin:box.ymax,box.zmin:box.zmax); +logim = ( A < arrivaltime); + +%dilate subvolume +se = segment3dp.tools('getse_helper',1); +largerlogim = imdilate(logim,se); +largerlogim = imdilate(largerlogim,se); +corelogim = imerode(logim,se); + +%Store to bw +bw(largerlogim) = uint8(255); + +%Get the added region +%logim = logical(largerlogim-logim); +bw(largerlogim) = min(bw(largerlogim),segment3dp.tools('calcthreshold3DP',S(largerlogim))); +%bw(logim) = segment3dp.tools('calcthreshold3DP',A(logim)); +bw(corelogim) = uint8(255); + +%Assign +SET(NO).LevelSet.BW(box.xmin:box.xmax,box.ymin:box.ymax,box.zmin:box.zmax) = bw; + +segment3dp.tools('storetoobject'); +segment3dp.tools('bwupdated'); +segment3dp.tools('update3DP'); + +%---------------------- +function pen3dp_buttonup(tool) %#ok +%---------------------- +global DATA + +%Manual draw +motionfunctions('pen3dp_motion',tool,1) +%This fixes icons tooltip +set(DATA.fig,'WindowButtonMotionFcn','segment(''toggleplaceholdermotion'')'); +set(DATA.fig,'WindowButtonUpFcn',''); +DATA.LevelSet.motionon = false; + +%Reset .Man +DATA.LevelSet.Man = int8(0)*DATA.LevelSet.Man; +segment3dp.tools('storetoobject'); +segment3dp.tools('bwupdated'); +segment3dp.tools('update3DP'); + +%------------------------------------ +function viewportpoints_buttonup(ind) %#ok +%------------------------------------ +%button up of moving points in viewport + +global DATA SET NO + +coord = getclickedcoord(DATA.LevelSet.ViewPort); + +set(DATA.fig,'WindowButtonMotionFcn',''); %'segment(''toggleplaceholdermotion'')'); +set(DATA.fig,'WindowButtonUpFcn',''); + +if ~isnan(coord(1)) + x = coord(1)+DATA.LevelSet.Box.xmin-1; %This adds if the the volume is cropped + y = coord(2)+DATA.LevelSet.Box.ymin-1; + z = coord(3)+DATA.LevelSet.Box.zmin-1; + + SET(NO).Point.X(ind) = x; + SET(NO).Point.Y(ind) = y; + SET(NO).Point.Z(ind) = z; + +end + +segment3dp.tools('addpointstoviewport'); + +for p = 1:length(DATA.ViewPanels) + if ~isequal(DATA.ViewPanelsType{p},'viewport') + viewfunctions('updatedrawlist',p) + drawfunctions('drawpanel',p) + end +end + +%See if we should update the line +if ~isempty(SET(NO).Line3D.Points) + if ismember(ind,SET(NO).Line3D.Points{1}) + segment3dp.linetools('createline','',SET(NO).Line3D.Points{1}); %Later possibility to have more lines + end +end diff --git a/source/calcfunctions.m b/source/calcfunctions.m index 4400a8c..f43ee70 100644 --- a/source/calcfunctions.m +++ b/source/calcfunctions.m @@ -12,139 +12,229 @@ feval(varargin{:}); % FEVAL switchyard end +%--------------------- +function segmentationintersection_helper(panel,t) +%----------------------- +%This is updates segmentation intersections for selected panel and timeframe. +global DATA + +[DATA.endointersectionx{panel}{t},DATA.endointersectiony{panel}{t}] = ... + calcfunctions('calcsegmentationintersections',panel,'epi',t,DATA.ViewPanelsType{panel}); + +[DATA.epiintersectionx{panel}{t},DATA.epiintersectiony{panel}{t}] = ... + calcfunctions('calcsegmentationintersections',panel,'epi',t,DATA.ViewPanelsType{panel}); + +%---------------------------------------------- +function [x,y] = resamplecurve(x,y,numpoints) %#ok +%---------------------------------------------- +%Calculate total length and remove duplicate points +global DATA + +if nargin==2 + numpoints = DATA.NumPoints; +end + +if length(x)>1 + len = sqrt(... + conv2(x',[1 -1],'valid').^2+... + conv2(y',[1 -1],'valid').^2); + len = [0;len(:)]; %Add zero first + len = cumsum(len); + tempind = find(conv2(len,[1;-1],'valid')~=0); %Remove doublets + len = [len(1);len(tempind+1)]; %used in interpolation later + x = [x(1); x(tempind+1)]; + y = [y(1); y(tempind+1)]; + totallength = len(end);%used in interpolation later + %Resample + x = interp1(len,x,linspace(0,totallength,numpoints),'pchip'); + y = interp1(len,y,linspace(0,totallength,numpoints),'pchip'); + + %assert correct clockwise order + [x,y] = mypoly2cw(x,y); + + xr = y; + yr = x; + mx = mean(xr); + my = mean(yr); + + [~,inda] = min(angle(complex(mx-xr,my-yr))); + x(1:(numpoints-inda)) = yr(inda+1:end); + y(1:(numpoints-inda)) = xr(inda+1:end); + x((numpoints+1-inda):end) = yr(1:inda); + y((numpoints+1-inda):end) = xr(1:inda); + +end + +%--------------------- +function preallocatesegmentationintersections(panels) %#ok +%----------------------- +%This is the preallocation of segmentation intersections Not doing the +%calculation within image rendering should be a large speed up. +global DATA SET + +%If no panels supplied these are the panels that needs calculation. A panel can be empty thats +%why this is needed. +if nargin == 0 + panels = find(DATA.ViewPanels(DATA.ViewPanels>0)); +end + +if length(DATA.endointersectionx)~=length(DATA.ViewPanels) + DATA.endointersectionx = cell(1,length(DATA.ViewPanels)); + DATA.endointersectiony = cell(1,length(DATA.ViewPanels)); + DATA.epiintersectionx = cell(1,length(DATA.ViewPanels)); + DATA.epiintersectiony = cell(1,length(DATA.ViewPanels)); + + %if the number of panels has changed we need to update all panel + %intersections. This overrides the input panels + panels = find(DATA.ViewPanels(DATA.ViewPanels>0)); +end + +for i = panels + DATA.endointersectionx{i} = cell(1,SET(DATA.ViewPanels(i)).TSize); + DATA.endointersectiony{i} = cell(1,SET(DATA.ViewPanels(i)).TSize); + DATA.epiintersectionx{i} = cell(1,SET(DATA.ViewPanels(i)).TSize); + DATA.epiintersectiony{i} = cell(1,SET(DATA.ViewPanels(i)).TSize); +end + +for i = panels + %Contour intersection + for t = 1:SET(DATA.ViewPanels(i)).TSize + segmentationintersection_helper(i,t) + end +end + %------------------------------------------ -function [edmax, MaxdiameterPoint, Zslice_no] = maxsaxdiameter(no,tf,type) +function [edmax, MaxdiameterPoint, Zslice_no] = maxsaxdiameter(no,tf,type) %#ok %------------------------------------------ %Get maximum endocardial diameter in short-axis cine stack -% Input: no - no of stack, -% tf - time frame, +% Input: no - no of stack, +% tf - time frame, % type - 'RV', 'LV' % Output: edmax - max LV/RV diameter % MaxdiameterPoint - points with the largest distance in form [x,y] % Zslice_no - slice number with largest LV/RV diameter -% +% global SET xres = SET(no).ResolutionX; yres = SET(no).ResolutionY; switch type - case 'LV' - edxall = squeeze(SET(no).EndoX(:,tf,:)); - edyall = squeeze(SET(no).EndoY(:,tf,:)); - - edmax = 0; - edmax_temp = 0; - MaxdiameterPoint = []; - Zslice_no=[]; + case 'LV' + edxall = squeeze(SET(no).EndoX(:,tf,:)); + edyall = squeeze(SET(no).EndoY(:,tf,:)); + + edmax = 0; + edmax_temp = 0; + MaxdiameterPoint = []; + Zslice_no=[]; + + for z = 1:SET(no).ZSize + edx = edxall(:,z); + if ~isnan(edx(1)) + edy = edyall(:,z); + edxmat = repmat(edx,1,length(edx)); + edymat = repmat(edy,1,length(edy)); + eddist = sqrt((xres*(edxmat'-edxmat)).^2+ ... + (yres*(edymat'-edymat)).^2); - for z = 1:SET(no).ZSize - edx = edxall(:,z); - if ~isnan(edx(1)) - edy = edyall(:,z); - edxmat = repmat(edx,1,length(edx)); - edymat = repmat(edy,1,length(edy)); - eddist = sqrt((xres*(edxmat'-edxmat)).^2+ ... - (yres*(edymat'-edymat)).^2); - - % edmax = max(edmax,max(eddist(:))); - edmax_temp=max(eddist(:)); - if edmax_temp>edmax - edmax=edmax_temp; - [row, col] = find(ismember(eddist, edmax)); - MaxdiameterPoint(1,:)=[edx(row(1)),edy(row(1))]; - MaxdiameterPoint(2,:)=[edx(col(1)),edy(col(1))]; - Zslice_no=z; % #slice number - end - end + % edmax = max(edmax,max(eddist(:))); + edmax_temp=max(eddist(:)); + if edmax_temp>edmax + edmax=edmax_temp; + [row, col] = find(ismember(eddist, edmax)); + MaxdiameterPoint(1,:)=[edx(row(1)),edy(row(1))]; + MaxdiameterPoint(2,:)=[edx(col(1)),edy(col(1))]; + Zslice_no=z; % #slice number end - %% In case of RV max diameter, first we find center point of LV based on EPI contour - % Then we finiding septum, and calculate the middle point of septum - % The last part is to find the intersection between line (center LV and center septum) with RV endo contur. - % This intersecton defines our maximal RV dimater. - case 'RV' - edmax = 0; - edmax_temp = 0; - MaxdiameterPoint=[]; - Zslice_no=[]; + end + end + % In case of RV max diameter, first we find center point of LV based on EPI contour + % Then we finiding septum, and calculate the middle point of septum + % The last part is to find the intersection between line (center LV and center septum) with RV endo contur. + % This intersecton defines our maximal RV dimater. + case 'RV' + edmax = 0; + edmax_temp = 0; + MaxdiameterPoint=[]; + Zslice_no=[]; + + edxall = squeeze(SET(no).RVEndoX(:,tf,:)); + edyall = squeeze(SET(no).RVEndoY(:,tf,:)); + epxLVall = squeeze(SET(no).EpiX(:,tf,:)); + epyLVall = squeeze(SET(no).EpiY(:,tf,:)); + + + %Center of Epi LV ROI for each slice + xLVcen=mean(epxLVall); + yLVcen=mean(epyLVall); + + % Convhull RV roi + for z = 1:SET(no).ZSize + edx = edxall(:,z); + edxLV=epxLVall(:,z); + if isnan(edxLV(1)) + continue + end + if ~isnan(edx(1)) + edy = edyall(:,z); + k=convhull(edx,edy); - edxall = squeeze(SET(no).RVEndoX(:,tf,:)); - edyall = squeeze(SET(no).RVEndoY(:,tf,:)); - epxLVall = squeeze(SET(no).EpiX(:,tf,:)); - epyLVall = squeeze(SET(no).EpiY(:,tf,:)); + xhull=edx(k); + yhull=edy(k); - - %Center of Epi LV ROI for each slice - xLVcen=mean(epxLVall); - yLVcen=mean(epyLVall); + len=diff(xhull).^2+diff(yhull).^2; - % Convhull RV roi - for z = 1:SET(no).ZSize - edx = edxall(:,z); - edxLV=epxLVall(:,z); - if isnan(edxLV(1)) - continue - end - if ~isnan(edx(1)) - edy = edyall(:,z); - k=convhull(edx,edy); - - xhull=edx(k); - yhull=edy(k); - - len=diff(xhull).^2+diff(yhull).^2; - - %%maximum length line segment is made out of the septum points. An addition - %to make this more robust is to pick out the n largest line segments and check the area of the concavity the maximum area concavity should be the LV. - [~,ind]=max(len); - a=[xhull(ind),yhull(ind)]; - b=[xhull(ind+1),yhull(ind+1)]; - - %find closest points on RV contour - [~,ind_a]=min((edx-a(1)).^2+(edy-a(2)).^2); - [~,ind_b]=min((edx-b(1)).^2+(edy-b(2)).^2); - - %%number of poinst between A and B - if (edx(ind_a) < edx(ind_a+1))&&(edx(ind_b) < edx(ind_b+1)) - noABx=[edx(1:ind_a-1); edx(ind_b+1:end)]; - else - noABx=edx(ind_a+1:ind_b-1); - end - - %% point which is in the middle between A and B - ind_midAB=ceil(length(noABx)/2); - % middle point - if ind_a <= ind_midAB - midRVab=[edx(end-(ind_midAB-ind_a)), edy(end-(ind_midAB-ind_a))]; - else - midRVab=[edx(ind_a-ind_midAB), edy(ind_a-ind_midAB)]; - - end - - %%line between center LV and centre of septal RV - x=[xLVcen(z), midRVab(1)]; - y=[yLVcen(z), midRVab(2)]; - p = polyfit(x,y,1); + %maximum length line segment is made out of the septum points. An addition + %to make this more robust is to pick out the n largest line segments and check the area of the concavity the maximum area concavity should be the LV. + [~,ind]=max(len); + a=[xhull(ind),yhull(ind)]; + b=[xhull(ind+1),yhull(ind+1)]; + + %find closest points on RV contour + [~,ind_a]=min((edx-a(1)).^2+(edy-a(2)).^2); + [~,ind_b]=min((edx-b(1)).^2+(edy-b(2)).^2); + + %number of poinst between A and B + if (edx(ind_a) < edx(ind_a+1))&&(edx(ind_b) < edx(ind_b+1)) + noABx=[edx(1:ind_a-1); edx(ind_b+1:end)]; + else + noABx=edx(ind_a+1:ind_b-1); + end + + % point which is in the middle between A and B + ind_midAB=ceil(length(noABx)/2); + % middle point + if ind_a <= ind_midAB + midRVab=[edx(end-(ind_midAB-ind_a)), edy(end-(ind_midAB-ind_a))]; + else + midRVab=[edx(ind_a-ind_midAB), edy(ind_a-ind_midAB)]; - %%calculate line - x_space=linspace(min(edx), max(edx),100); - y_space=p(1)*x_space+p(2); - - %% Intersection between the line LV - septal centre and RV segmentation - [xi,yi] = polyxpoly(edx,edy,x_space,y_space); - - %% Max RV diameter - edmax_temp=sqrt((xres*diff(xi)).^2+(yres*diff(yi)).^2); - if edmax_temp>edmax - edmax=edmax_temp; - MaxdiameterPoint(1,:)=[xi(1),yi(1)]; - MaxdiameterPoint(2,:)=[xi(2),yi(2)]; - Zslice_no=z; % #slice number - end - end end + + % line between center LV and centre of septal RV + x=[xLVcen(z), midRVab(1)]; + y=[yLVcen(z), midRVab(2)]; + p = polyfit(x,y,1); + + % calculate line + x_space=linspace(min(edx), max(edx),100); + y_space=p(1)*x_space+p(2); + + % Intersection between the line LV - septal centre and RV segmentation + [xi,yi] = polyxpoly(edx,edy,x_space,y_space); + + % Max RV diameter + edmax_temp=sqrt((xres*diff(xi)).^2+(yres*diff(yi)).^2); + if edmax_temp>edmax + edmax=edmax_temp; + MaxdiameterPoint(1,:)=[xi(1),yi(1)]; + MaxdiameterPoint(2,:)=[xi(2),yi(2)]; + Zslice_no=z; % #slice number + end + end + end end - %---------------------------------------- function [N,xc,yc,zc] = lsplanefit(x,y,z) %#ok, used by makecut %--------------------------------------- @@ -169,39 +259,39 @@ % Syy = y*y'; % Sxz = x*z'; % Syz = y*z'; -% +% % %using that there is no problem with fixating one param in the equation and % %that the point cloud is zero centered i.e sum(x)=0 etc we get that it is % %sufficient to solve the below system % A = [Sxx,Sxy;Sxy,Syy]; % B = -[Sxz;Syz]; -% +% % params = A\B; % N = [params;1]; %using svd A=[x;y;z]; -[U,~,~] = svd(A); +[U,~,~] = svd(A,'econ'); N = cross(U(:,1),U(:,2)); % point = [0,0,0]; % normal = N'; -%# a plane is a*x+b*y+c*z+d=0 -%# [a,b,c] is the normal. Thus, we have to calculate -%# d and we're set +% a plane is a*x+b*y+c*z+d=0 +% [a,b,c] is the normal. Thus, we have to calculate +% d and we're set % d = -point*normal'; %'# dot product for less typing -% %# create x,y +% % create x,y % [xx,yy]=ndgrid(linspace(-1,1,10),linspace(-1,1,10)); -% -% %# calculate corresponding z +% +% % calculate corresponding z % zz = (-normal(1)*xx - normal(2)*yy - d)/normal(3); -%# plot the surface +% plot the surface % figure % surf(xx,yy,zz) -% hold on +% hold on % plot3(x',y',z','k*') %---------------------- @@ -228,15 +318,22 @@ function calcvolume(no) %#ok docomp=true; elseif SET(no).Longaxis > 1%SET(NO).Longaxis > 1 docomp = true; -end; +end if SET(no).Rotated calclvvolumepolar(no); return; -end; +end -ind = (findfunctions('findslicewithendo',no))|(findfunctions('findslicewithepi',no)); %Accepts empty endo and epi if exist +% needtodo = false; +% if ~isempty(SET(no).EndoX) +% needtodo = true; +% end +% if ~isempty(SET(no).EpiX) +% needtodo = true; +% end +ind = (findfunctions('findslicewithendo',no))|(findfunctions('findslicewithepi',no)); %Accepts empty endo and epi if exist if ~any(ind) SET(no).LVV = nan(1,SET(no).TSize); SET(no).EPV = SET(no).LVV; @@ -253,74 +350,96 @@ function calcvolume(no) %#ok if nargout>0 varargout = cell(1,1); varargout{1} = []; - end; + end if nargout>1 varargout{2} = []; - end; + end return; -end; +end + %Find what slices to do if SET(no).ZSize>1 pos = find(ind); else pos = 1; -end; -LVVall = zeros(length(pos),SET(no).TSize); -EPVall = zeros(length(pos),SET(no).TSize); +end +% LVVall = zeros(length(pos),SET(no).TSize); +% EPVall = zeros(length(pos),SET(no).TSize); % if isempty(SET(no).EndoX) % %This far then create % SET(no).EndoX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); -% SET(no).EndoY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); -% end; -% +% SET(no).EndoY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% end +% % if isempty(SET(no).EpiX) % %This far then create % SET(no).EpiX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); -% SET(no).EpiY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); -% end; +% SET(no).EpiY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% end %Loop over all segmented slices -for sloop=1:length(pos) - for tloop=1:SET(no).TSize - if ~isempty(SET(no).EndoX)&&~isnan(SET(no).EndoX(1,tloop,pos(sloop))) - A = stablepolyarea(... - SET(no).ResolutionY*SET(no).EndoY(1:end-1,tloop,pos(sloop)),... - SET(no).ResolutionX*SET(no).EndoX(1:end-1,tloop,pos(sloop))); - LVVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; %to cm3 - end; - if ~isempty(SET(no).EpiX)&&~isnan(SET(no).EpiX(1,tloop,pos(sloop))) - A = stablepolyarea(... - SET(no).ResolutionY*SET(no).EpiY(1:end-1,tloop,pos(sloop)),... - SET(no).ResolutionX*SET(no).EpiX(1:end-1,tloop,pos(sloop))); - EPVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; %to cm3 - end; - end; -end; +if ~isempty(SET(no).EndoX) + LVVall = squeeze(polyarea(SET(no).ResolutionY*SET(no).EndoY(1:end-1,:,pos),... + SET(no).ResolutionX*SET(no).EndoX(1:end-1,:,pos))*(SET(no).SliceThickness+SET(no).SliceGap)/1000); + if length(pos)>1 + LVVall = nansum(LVVall'); + end +else + LVVall = zeros(1,SET(no).TSize); +end -%Sum to get total volume -if length(pos)>1 - SET(no).LVV = sum(LVVall); - SET(no).EPV = sum(EPVall); +if ~isempty(SET(no).EpiX) + EPVall = squeeze(polyarea(SET(no).ResolutionY*SET(no).EpiY(1:end-1,:,pos),... + SET(no).ResolutionX*SET(no).EpiX(1:end-1,:,pos))*(SET(no).SliceThickness+SET(no).SliceGap)/1000); + if length(pos)>1 + EPVall = nansum(EPVall'); + end else - SET(no).LVV = LVVall; - SET(no).EPV = EPVall; -end; + EPVall = zeros(1,SET(no).TSize); +end + + +% for sloop=1:length(pos) +% for tloop=1:SET(no).TSize +% if ~isempty(SET(no).EndoX)&&~isnan(SET(no).EndoX(1,tloop,pos(sloop))) +% A = stablepolyarea(... +% SET(no).ResolutionY*SET(no).EndoY(1:end-1,tloop,pos(sloop)),... +% SET(no).ResolutionX*SET(no).EndoX(1:end-1,tloop,pos(sloop))); +% LVVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; %to cm3 +% end +% if ~isempty(SET(no).EpiX)&&~isnan(SET(no).EpiX(1,tloop,pos(sloop))) +% A = stablepolyarea(... +% SET(no).ResolutionY*SET(no).EpiY(1:end-1,tloop,pos(sloop)),... +% SET(no).ResolutionX*SET(no).EpiX(1:end-1,tloop,pos(sloop))); +% EPVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; %to cm3 +% end +% end +% end + +%Sum to get total volume +% if length(pos)>1 +% SET(no).LVV = sum(LVVall'); +% SET(no).EPV = sum(EPVall'); +% else +SET(no).LVV = LVVall; +SET(no).EPV = EPVall; +% end SET(no).LVM = SET(no).EPV-SET(no).LVV+SET(no).PV; - + if nargout>0 varargout = cell(1,1); varargout{1} = LVVall; -end; +end if nargout>1 varargout{2} = EPVall; -end; +end if nargout>2 varargout{3} = 1.05*(EPVall-LVVall); %LVM in g, NOTE not include Papillary volume (PV) -end; +end %Update EDV,ESV SET(no).EDV = SET(no).LVV(SET(no).EDT); @@ -333,9 +452,9 @@ function calcvolume(no) %#ok if (SET(no).ZSize>2)&&docomp LVVnocomp = SET(no).LVV; EPVnocomp = SET(no).EPV; - + for rloop=1:1 %Converges very quickly - + %Calculate compensation mechanism if (SET(no).LVV(SET(no).EDT)-SET(no).LVV(SET(no).EST)~=0) pp = SET(no).LVV; @@ -345,20 +464,20 @@ function calcvolume(no) %#ok pp = min(max(pp,0),1); else pp = ones(size(SET(no).LVV)); - end; + end err = zeros(1,20); - + %Compensate %pp = pp.*pp; - + %Check if autodetect if SET(no).AutoLongaxis for loop=1:20 - + %Calculate slices slices = (loop-1); %Convert to mm slices = slices/(SET(no).SliceThickness+SET(no).SliceGap); %Convert to slices - + sloop=1; SET(no).LVV = LVVnocomp; %Restore SET(no).EPV = EPVnocomp; @@ -368,27 +487,27 @@ function calcvolume(no) %#ok SET(no).EPV = SET(no).EPV-min(slices,1)*EPVall(sloop,:).*pp; slices = slices-1; sloop = sloop+1; - end; - + end + %Calculate error err(loop) = max(SET(no).EPV-SET(no).LVV+SET(no).PV)-min(SET(no).EPV-SET(no).LVV+SET(no).PV); - end; %loop + end %loop [~,inde] = min(err); SET(no).Longaxis = inde; - end; %autodetect - + end %autodetect + %Convert to slices => 1mm between, first is zero slices = (SET(no).Longaxis-1); if isempty(slices) slices = 0; end slices = slices/(SET(no).SliceThickness+SET(no).SliceGap); - + %Compensate the last time, now store it! sloop=1; SET(no).LVV = LVVnocomp; %Restore SET(no).EPV = EPVnocomp; - + %Check if need to fix with outline if ~isempty(SET(no).EndoX) zloop = find(not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,:)))); @@ -402,76 +521,22 @@ function calcvolume(no) %#ok zloop = SET(no).CurrentSlice; else zloop = zloop(1); - end; - - %Make sure that it is updated - %if docomp - % updatemodeldisplay; - %end; + end while (slices>0)&&(sloop<=size(LVVall,1)) %Remove whole slice or fraction of it. SET(no).LVV = SET(no).LVV-min(slices,1)*LVVall(sloop,:).*pp; SET(no).EPV = SET(no).EPV-min(slices,1)*EPVall(sloop,:).*pp; - - [xofs,yofs] = calcoffset(zloop,'montage'); - - %Need to fix with outline? - if 0%get(DATA.Handles.volumeoutlinecheckbox,'value') - for tloop=1:SET(no).TSize - if ~isempty(SET(no).EndoX) - SET(no).EndoXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - (SET(no).EndoX(:,tloop,zloop)-SET(no).CenterX)*(1-pp(tloop)*min(1,slices))+SET(no).CenterX+xofs; - SET(no).EndoYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - (SET(no).EndoY(:,tloop,zloop)-SET(no).CenterY)*(1-pp(tloop)*min(1,slices))+SET(no).CenterY+yofs; - end - if ~isempty(SET(no).EpiX) - SET(no).EpiXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - (SET(no).EpiX(:,tloop,zloop)-SET(no).CenterX)*(1-pp(tloop)*min(1,slices))+SET(no).CenterX+xofs; - SET(no).EpiYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - (SET(no).EpiY(:,tloop,zloop)-SET(no).CenterY)*(1-pp(tloop)*min(1,slices))+SET(no).CenterY+yofs; - end - end; - else - for tloop=1:SET(no).TSize - if ~isempty(SET(no).EndoX) - SET(no).EndoXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - SET(no).EndoX(:,tloop,zloop)+xofs; - SET(no).EndoYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - SET(no).EndoY(:,tloop,zloop)+yofs; - end - if ~isempty(SET(no).EpiX) - SET(no).EpiXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - SET(no).EpiX(:,tloop,zloop)+xofs; - SET(no).EpiYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... - SET(no).EpiY(:,tloop,zloop)+yofs; - end - end; - end; zloop = zloop+1; slices = slices-1; sloop = sloop+1; - end; - end; %rloop + end + end %rloop if DATA.Silent return; - end; - - for loop=1:length(DATA.ViewPanels) - if isequal(no,DATA.ViewPanels(loop)) - if 0%isequal(get(DATA.Handles.volumeoutlinecheckbox,'value'),1) &&... - ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montage','montagerow','montagefit','sax3'}) - set(DATA.Handles.endocontour(loop),'LineStyle',':'); - set(DATA.Handles.epicontour(loop),'LineStyle',':'); - else - set(DATA.Handles.endocontour(loop),'LineStyle','-'); - set(DATA.Handles.epicontour(loop),'LineStyle','-'); - end; - end; - end; - -end; %If docompensation + end +end %If docompensation %----------------------------- @@ -500,7 +565,7 @@ function calclvvolumepolar(no) SET(no).EF = 0; SET(no).SV = 0; return; -end; +end %Find rotation axis, rotation around x-axis my = SET(no).RotationCenter; @@ -518,14 +583,14 @@ function calclvvolumepolar(no) else dxds = econv3(temp,[-1;1]); dxds = dxds(2:end,:,:); %Different convolves have different "outside" - end; + end y = double(SET(no).ResolutionY)*double((SET(no).EndoY(:,:,ind)-my))/10; %cm vol = pi*alphapart*y.^2.*sign(y).*dxds; vol = nansum(nansum(vol,1),3); SET(no).LVV = vol; %Store else SET(no).LVV = zeros(1,SET(no).TSize); -end; +end %--- Calc epi volume if ~isempty(SET(no).EpiX) && ~all(isnan(SET(no).EpiX(:))) @@ -536,20 +601,20 @@ function calclvvolumepolar(no) else dxds = econv3(temp,[-1;1]); dxds = dxds(2:end,:,:); %Different convolves have different "outside" - end; + end y = double(SET(no).ResolutionY)*double(SET(no).EpiY(:,:,ind)-my)/10; %cm vol = pi*alphapart*y.^2.*sign(y).*dxds; vol = nansum(nansum(vol,1),3); SET(no).EPV = vol; %Store else - SET(no).EPV = zeros(1,SET(no).TSize); -end; + SET(no).EPV = zeros(1,SET(no).TSize); +end %------------------------------------ function [varargout] = calcrvvolume(no) %------------------------------------ %Calculate RV volume. no is the image stack. -%The RV volume calculation does not involve any longaxis +%The RV volume calculation does not involve any longaxis %compensation. global SET @@ -557,26 +622,26 @@ function calclvvolumepolar(no) needtodo = false; if ~isempty(SET(no).RVEndoX) needtodo = true; -end; +end if ~isempty(SET(no).RVEpiX) needtodo = true; -end; +end if SET(no).Rotated calcrvvolumepolar(no); return; -end; - +end + if ~needtodo SET(no).RVV = zeros(1,SET(no).TSize); SET(no).RVEPV = zeros(1,SET(no).TSize); SET(no).RVEDV = 0; - SET(no).RVESV = 0; + SET(no).RVESV = 0; SET(no).RVSV = 0; SET(no).RVEF = 0; SET(no).RVM = 0; varargout = cell(1,nargout); return; -end; +end ind = (findfunctions('findslicewithrvendo',no))|(findfunctions('findslicewithrvepi',no)); %Accepts empty endo and epi if exist @@ -585,7 +650,7 @@ function calclvvolumepolar(no) pos = find(ind); else pos = 1; -end; +end RVVall = zeros(length(pos),SET(no).TSize); EPVall = zeros(length(pos),SET(no).TSize); @@ -599,37 +664,37 @@ function calclvvolumepolar(no) SET(no).ResolutionY*SET(no).RVEndoY(1:end-1,tloop,pos(sloop)),... SET(no).ResolutionX*SET(no).RVEndoX(1:end-1,tloop,pos(sloop))); RVVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; - end; - end; - end; -end; -SET(no).RVV=sum(RVVall,1); %Buggfix for RV calculation. Addded ,1 EH: + end + end + end +end +SET(no).RVV=nansum(RVVall,1); %Buggfix for RV calculation. Addded ,1 EH: SET(no).RVEDV = SET(no).RVV(SET(no).EDT); SET(no).RVESV = SET(no).RVV(SET(no).EST); SET(no).RVEPV = zeros(1,SET(no).TSize); if ~isempty(SET(no).RVEpiX) - for sloop=1:length(pos) + for sloop=1:length(pos) for tloop=1:SET(no).TSize if ~isnan(SET(no).RVEpiX(1,tloop,pos(sloop))) A = stablepolyarea(... SET(no).ResolutionY*SET(no).RVEpiY(1:end-1,tloop,pos(sloop)),... SET(no).ResolutionX*SET(no).RVEpiX(1:end-1,tloop,pos(sloop))); EPVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; - end; - end; - end; -end; -SET(no).RVEPV=sum(EPVall,1); %Buggfix for RV calculation. Addded ,1 EH: + end + end + end +end +SET(no).RVEPV=nansum(EPVall,1); %Buggfix for RV calculation. Addded ,1 EH: if nargout>0 varargout = cell(1,1); varargout{1} = RVVall; -end; +end if nargout>1 varargout{2} = EPVall; -end; +end %----------------------------- function calcrvvolumepolar(no) @@ -649,7 +714,7 @@ function calcrvvolumepolar(no) SET(no).RVEF = 0; SET(no).RVSV = 0; return; -end; +end %Find rotation axis, rotation around x-axis my = SET(no).RotationCenter; @@ -661,20 +726,20 @@ function calcrvvolumepolar(no) if ~isempty(SET(no).RVEndoX) %Calc dx/ds temp = SET(no).ResolutionX*cat(1,SET(no).RVEndoX(:,:,ind),SET(no).RVEndoX(1,:,ind))/10; %cm - if ndims(temp)==2 + if ismatrix(temp) dxds = conv2(temp,[1;-1],'same'); dxds = dxds(1:(end-1),:,:); %Remove "outside" data else dxds = econv3(temp,[-1;1]); dxds = dxds(2:end,:,:); %Different convolves have different "outside" - end; + end y = SET(no).ResolutionY*(SET(no).RVEndoY(:,:,ind)-my)/10; %cm vol = pi*alphapart*y.^2.*sign(y).*dxds; vol = nansum(nansum(vol,1),3); SET(no).RVV = vol; %Store else SET(no).RVV = zeros(1,SET(no).TSize); -end; +end %--- Calc epi volume if ~isempty(SET(no).RVEpiX) @@ -685,14 +750,14 @@ function calcrvvolumepolar(no) else dxds = econv3(temp,[-1;1]); dxds = dxds(2:end,:,:); %Different convolves have different "outside" - end; + end y = SET(no).ResolutionY*(SET(no).RVEpiY(:,:,ind)-my)/10; %cm vol = pi*alphapart*y.^2.*sign(y).*dxds; vol = nansum(nansum(vol,1),3); SET(no).RVEPV = vol; %Store else - SET(no).RVEPV = zeros(1,SET(no).TSize); -end; + SET(no).RVEPV = zeros(1,SET(no).TSize); +end %------------------------- function volume_helper(no) @@ -701,7 +766,7 @@ function volume_helper(no) %Lots of checks to prevent NaN or Inf to be presented %when some of the data are missing. -global SET +global SET %Find zeros in volume SET(no).LVV(SET(no).LVV==0) = NaN; @@ -714,7 +779,7 @@ function volume_helper(no) %Prevent that when endo is empty that epi may be viewed if not(isnan(SET(no).EPV(1)))&&(isnan(SET(no).LVV(1))) SET(no).LVV = zeros(size(SET(no).LVV)); -end; +end %Find peak ejection rate, peak filling rate if SET(no).TSize>2 @@ -736,7 +801,7 @@ function volume_helper(no) SET(no).RVPER = 0; SET(no).RVPFRT = 1; SET(no).RVPERT = 1; -end; +end %Store LV-EDV,ESV,SV SET(no).EDV = SET(no).LVV(SET(no).EDT)-SET(no).PV(SET(no).EDT); @@ -753,7 +818,7 @@ function volume_helper(no) SET(no).EF = SET(no).SV/SET(no).EDV; %Ejection fraction else SET(no).EF = NaN; -end; +end if ~isempty(SET(no).RVEndoX) %Store RV-EDV,ESV,SV @@ -766,32 +831,130 @@ function volume_helper(no) SET(no).RVEF = 0; else SET(no).RVEF = SET(no).RVSV/SET(no).RVEDV; %Ejection fraction - end; -end; + end +end if isnan(SET(no).RVEDV) SET(no).RVEDV = 0; -end; +end if isnan(SET(no).RVESV) SET(no).RVESV = 0; -end; +end if isnan(SET(no).RVSV) SET(no).RVSV = 0; -end; +end if isnan(SET(no).RVEF) SET(no).RVEF = 0; -end; +end if isequal(SET(no).EDT,SET(no).EST) SET(no).RVESV=NaN; SET(no).RVSV=NaN; SET(no).RVEF=NaN; end +%------------------------------------- +function age = calcageyearfraction(age,ageunit) %#ok +%------------------------------------- +%Calculates age as fraction of the year +denominator = 372; %corresponds to the 12month*31days for easier calculations +switch lower(ageunit) + case 'm' %months + numerator = 31; + case 'd' %days + numerator = 1; + case 'w' %weeks + numerator = 7; % to calculate into corresponding number of days + case 'y' % years + return; % no calculation necessary +end +age = age*numerator/denominator; + +%------------------------------------- +function [age,ageunit] = calcagewithunits(age) %#ok +%------------------------------------- +%Calculates age that is given as fraction of the year into "normal" +denominator = 372; %corresponds to the 12month*31days for easier calculations +numdaysinmonth = 31; +if not(isempty(age)) + if age >= 1 % corresponds to years + if age < 2 + ageunit = dprintf('year'); + else + ageunit = dprintf('years'); + end + else + newage = age*denominator; + if newage < numdaysinmonth % corresponds to days + age = newage; + if age < 2 + ageunit = dprintf('day'); + else + ageunit = dprintf('days'); + end + else %corresponds to months + age = newage/numdaysinmonth; + if age < 2 + ageunit = dprintf('month'); + else + ageunit = dprintf('months'); + end + end + end +else + ageunit = ''; +end + +%------------------------------------- +function [agedigits,ageunit] = calcagefrombirthdate(birthdate, acqusitiondate) %#ok +%------------------------------------- +%Calculates age as difference between birthdate and acquisition date + +switch length(birthdate) + case 4 + birthinputformat = 'yyyy'; + case 8 + birthinputformat = 'yyyyMMdd'; + otherwise + agedigits = []; + ageunit = ''; + return; +end + +try + datedifference = between(datetime(birthdate,'InputFormat',birthinputformat),... + datetime(acqusitiondate,'InputFormat','yyyyMMdd'),... + {'years','months','days'}); +catch me + mydispexception(me) + agedigits = []; + ageunit = ''; + return +end + +% split into number of years/moths/days +[numyears,nummonths,numdays] = split(datedifference,{'years','months','days'}); +% set up digits and units +if numyears > 0 % years digit + agedigits = numyears; + ageunit = 'y'; +else + if nummonths > 0 + agedigits = nummonths; + ageunit = 'm'; + else + agedigits = numdays; + ageunit = 'd'; + end +end + %------------------------------------- function bsa = calcbsa(weight,height) %#ok %------------------------------------- %Calculates BSA. Formula based on Mosteller %weight in kilo and height in cm. + +%This code is duplicated in segdicomtags to avoid compiler leak of +%segmentserversorter bsa = sqrt(weight*height/3600); %----------------------------------- @@ -812,7 +975,7 @@ function volume_helper(no) if nargin<2 no = NO; -end; +end if not(isa(z,'int16')) && ~isempty(SET(no).IntensityOffset) %z = im*SET(no).IntensityScaling+SET(no).IntensityOffset; im = (z-SET(no).IntensityOffset)/SET(no).IntensityScaling; @@ -821,18 +984,23 @@ function volume_helper(no) end %------------------------------- -function z = calctruedata(im,no) +function z = calctruedata(im,no) %------------------------------- %Calculate true image intensities (as before Segment internal %normalization). Uses IntensityScaling and IntensityOffset stored -%in SET structure. im is input image, and no is image stack, +%in SET structure. im is input image, and no is image stack, %where to take the scaling from. global SET NO if nargin<2 no = NO; -end; +end + +if isequal(SET(no).IntensityScaling,1) && isequal(SET(no).IntensityOffset,0) + z = im; + return; +end if ~isempty(SET(no).IntensityScaling) if not(isa(im,'int16')) @@ -844,19 +1012,19 @@ function volume_helper(no) z = (im-0.5)*2*SET(no).VENC; else z = im; -end; +end %---------------------------------------- function radvel = calcradialvelocity(no) %#ok %---------------------------------------- -%Calculate radial velocity of the endocardium. +%Calculate radial velocity of the endocardium. %Forward difference is used. global SET NO if nargin<1 no = NO; -end; +end %Calc radius rad = calcendoradius(no); @@ -870,71 +1038,70 @@ function volume_helper(no) temp = cat(2,temp,temp(:,end,:)); else temp = zeros(size(rad)); - end; -end; + end +end temp = temp(:,2:end,:); %Remove first timeframe, wrong derivate radvel = temp/10; %=> cm/s %-------------------------- -function [meanarea,area]=calcroiarea(no,roino,thisframeonly) %#ok +function [meanarea,area] = calcroiarea(no,roino) %#ok %-------------------------- %Calculates roi area (helper fcn) +%no: current image stack +%roino: selected ROI in current image stack +global DATA SET -global SET - -if nargin < 3 - thisframeonly = false; -end -if thisframeonly +if DATA.DoThisFrameOnly tvec = SET(no).CurrentTimeFrame; else tvec = SET(no).Roi(roino).T; end -area=nan(1,SET(no).TSize); -for tloop=tvec - if not(isnan(SET(no).Roi(roino).Y(1,tloop))) - area(tloop)= (1/100)*stablepolyarea(... - SET(no).ResolutionY*SET(no).Roi(roino).Y(:,tloop),... - SET(no).ResolutionX*SET(no).Roi(roino).X(:,tloop)); - end +if ~isfield(SET(no).Roi(roino),'Area') || isempty(SET(no).Roi(roino).Area) + area = nan(1,SET(no).TSize); +else + area = SET(no).Roi(roino).Area; end -if thisframeonly - area = area(tvec); + +for tloop = tvec + if not(isnan(SET(no).Roi(roino).Y(1,tloop))) + area(tloop) = (1/100)*stablepolyarea(... + SET(no).ResolutionY*SET(no).Roi(roino).Y(:,tloop),... + SET(no).ResolutionX*SET(no).Roi(roino).X(:,tloop)); + end end -meanarea=mynanmean(area); + +meanarea = mynanmean(area); %----------------------------------------------------------------------------- -function [m,sd,rmin,rmax] = calcroiintensity(no,roino,normalize,thisframeonly) %#ok +function [m,sd,rmin,rmax] = calcroiintensity(no,roino) %#ok %----------------------------------------------------------------------------- %Calculates intensity within a ROI (helper fcn) -global SET -if nargin < 3 - normalize = false; -end -if nargin < 4 - thisframeonly = false; -end +%no: current image stack +%roino: selected ROI in current image stack +global DATA SET -if thisframeonly +if DATA.DoThisFrameOnly tvec = SET(no).CurrentTimeFrame; else tvec = SET(no).Roi(roino).T; end -m = nan(1,SET(no).TSize); -sd = m; -rmin = m; -rmax = m; +if ~isfield(SET(no).Roi(roino),'Mean') || isempty(SET(no).Roi(roino).Mean) + m = nan(1,SET(no).TSize); + sd = m; +else + m = SET(no).Roi(roino).Mean; + sd = SET(no).Roi(roino).StD; +end +rmin = nan(1,SET(no).TSize); +rmax = rmin; + z = SET(no).Roi(roino).Z; -for tloop=tvec +for tloop = tvec if not(isnan(SET(no).Roi(roino).Y(1,tloop))) - if normalize - temp = SET(no).IM(:,:,tloop,z); - else - temp = calctruedata(SET(no).IM(:,:,tloop,z),no); - end; + temp = calctruedata(SET(no).IM(:,:,tloop,z),no); roimask = segment('createmask',... [SET(no).XSize SET(no).YSize],... SET(no).Roi(roino).Y(:,tloop),... @@ -945,18 +1112,10 @@ function volume_helper(no) sd(tloop) = std(temp(ind)); rmin(tloop) = min(temp(ind)); rmax(tloop) = max(temp(ind)); - end; + end end end -if thisframeonly - m = m(tvec); - sd = sd(tvec); - rmin = rmin(tvec); - rmax = rmax(tvec); -end - - %----------------------------------------------- function res = calcmyocardvolume(numsectors,no,tf) %#ok %----------------------------------------------- @@ -968,22 +1127,22 @@ function volume_helper(no) if nargin<2 no = NO; -end; +end if nargin < 3 tf = SET(no).CurrentTimeFrame; end - + res = nan([numsectors SET(no).ZSize]); if isempty(SET(no).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end if isempty(SET(no).EpiX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end numpoints = DATA.Pref.RadialProfiles; @@ -996,9 +1155,9 @@ function volume_helper(no) endoy = SET(no).EndoY(:,tf,:); epix = SET(no).EpiX(:,tf,:); epiy = SET(no).EpiY(:,tf,:); -end; +end -for slice=1:SET(no).ZSize +for slice=1:SET(no).ZSize if not(isnan(epix(1,slice))) if numsectors == 1 res(1,slice) = 1e-3*(SET(no).SliceThickness+SET(no).SliceGap)*... @@ -1017,7 +1176,7 @@ function volume_helper(no) meanyendo = meanyepi; else [meanxendo,meanyendo,endosectors] = findmeaninsectorslice('endo',numpoints,tf,slice,numsectors,no); - end; + end for loop=1:numsectors if episectors(loop)<=episectors(loop+1) @@ -1030,7 +1189,7 @@ function volume_helper(no) tempepiy = [... epiy(episectors(loop):numpoints,slice) ; ... epiy(1:episectors(loop+1),slice)]; - end; + end if isnan(endox(1,slice)) tempendox = repmat(meanxendo,size(tempepix)); @@ -1046,8 +1205,8 @@ function volume_helper(no) tempendoy = [... endoy(endosectors(loop):numpoints,slice) ; ... endoy(1:endosectors(loop+1),slice)]; - end; - end; + end + end %Calc volume in [ml] res(loop,slice) = 1e-3*(SET(no).SliceThickness+SET(no).SliceGap)*... @@ -1055,7 +1214,7 @@ function volume_helper(no) SET(no).ResolutionY*[tempendoy;flipud(tempepiy);tempendoy(1)],... SET(no).ResolutionX*[tempendox;flipud(tempepix);tempendox(1)]); - end; + end %correct the volume so the total volume in the current slice is correct if ~isnan(endox(1,slice)) slicevolume = 1e-3*(SET(no).SliceThickness+SET(no).SliceGap)*... @@ -1068,11 +1227,11 @@ function volume_helper(no) SET(no).ResolutionY*[tempendoy;flipud(epiy(:,slice));tempendoy],... SET(no).ResolutionX*[tempendox;flipud(epix(:,slice));tempendox]); end - correction = slicevolume/sum(res(:,slice)); + correction = slicevolume/nansum(res(:,slice)); res(:,slice) = res(:,slice)*correction; end - end; -end; + end +end %--------------------------------- function rad = calcendoradius(no) @@ -1085,13 +1244,13 @@ function volume_helper(no) if nargin<1 no = NO; -end; +end if isempty(SET(no).EndoX) rad = zeros(DATA.Pref.RadialProfiles,SET(no).TSize,SET(no).ZSize); myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end %Upsample model if not(DATA.Pref.RadialProfiles==DATA.NumPoints) @@ -1099,11 +1258,11 @@ function volume_helper(no) else endox = SET(no).EndoX; endoy = SET(no).EndoY; -end; +end rad = zeros(DATA.Pref.RadialProfiles,SET(no).TSize,SET(no).ZSize); for zloop=1:SET(no).ZSize - for tloop=1:SET(no).TSize + for tloop=1:SET(no).TSize if SET(no).EndoCenter %Calc mean meanx = mean(SET(no).EndoX(:,tloop,zloop)); @@ -1111,14 +1270,14 @@ function volume_helper(no) else meanx = mean(SET(no).EpiX(:,tloop,zloop)); meany = mean(SET(no).EpiY(:,tloop,zloop)); - end; + end %Calc radius rad(:,tloop,zloop) = sqrt(... ((endox(:,tloop,zloop)-meanx)*SET(no).ResolutionX).^2+... ((endoy(:,tloop,zloop)-meany)*SET(no).ResolutionY).^2); - end; -end; + end +end %-------------------------------- function rad = calcepiradius(no) @@ -1131,13 +1290,13 @@ function volume_helper(no) if nargin<1 no = NO; -end; +end if isempty(SET(no).EpiX) rad = zeros(DATA.Pref.RadialProfiles,SET(no).TSize,SET(no).ZSize); myfailed('No LV epicardium available.',DATA.GUI.Segment); return; -end; +end %Upsample model if not(DATA.Pref.RadialProfiles == DATA.NumPoints) @@ -1145,7 +1304,7 @@ function volume_helper(no) else epix = SET(no).EpiX; epiy = SET(no).EpiY; -end; +end rad = zeros(DATA.Pref.RadialProfiles,SET(no).TSize,SET(no).ZSize); for zloop=1:SET(no).ZSize @@ -1154,18 +1313,18 @@ function volume_helper(no) if SET(no).EndoCenter && ~isnan(SET(no).EndoX(1,tloop,zloop)) %Calc mean meanx = mean(SET(no).EndoX(:,tloop,zloop)); - meany = mean(SET(no).EndoY(:,tloop,zloop)); + meany = mean(SET(no).EndoY(:,tloop,zloop)); else meanx = mean(SET(no).EpiX(:,tloop,zloop)); meany = mean(SET(no).EpiY(:,tloop,zloop)); - end; - + end + %Calc radius rad(:,tloop,zloop) = sqrt(... (SET(no).ResolutionX*(epix(:,tloop,zloop)-meanx)).^2+... (SET(no).ResolutionY*(epiy(:,tloop,zloop)-meany)).^2); - end; -end; + end +end %------------------------------------------------------ function [wallthickness,endox,endoy,epix,epiy] = calcwallthickness(sectors,no) %#ok @@ -1182,12 +1341,12 @@ function volume_helper(no) if isempty(SET(no).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end if isempty(SET(no).EpiX) myfailed('No LV epicardium available.',DATA.GUI.Segment); return; -end; +end pos = find(findfunctions('findslicewithendo',no)&findfunctions('findslicewithepi',no)); nslices = length(pos); @@ -1195,7 +1354,7 @@ function volume_helper(no) if length(nslices)<1 myfailed('Need more than one segmented slice.',DATA.GUI.Segment); return; -end; +end %Calc radius endorad = calcendoradius(no); @@ -1247,28 +1406,187 @@ function volume_helper(no) end %--------------------------------------------------------------------- -function [xout,yout] = calcsegmentationintersections(no,type,viewtype) %#ok +function [xout,yout] = calcsegmentationintersections(panel,type,t,viewtype) %#ok %--------------------------------------------------------------------- %Calculates intersections between segmentation in image stacks. -%no is image stack and type is endo or epi, can also be rvendo etc. -%the type is a string that dynamically calls a field of the SET struct. +%Input is panel and type is endo or epi, can also be rvendo etc. +%the type is a string that dynamically calls a field of the SET struct. t +%is the current timeframe in the panel. This should be used to calculate +%the matching phase in the other image stacks. global DATA SET -if nargin < 3 - viewtype = 'one'; -end +no = DATA.ViewPanels(panel); %Always return something xout = nan; yout = nan; + +%We dont display intersections in montage views +if strcmp(DATA.ViewPanelsType{panel},{'montage','montagesegmented','montagerow'}) + return +end + +%this is the strings for the contour we are calculating intersections for espot = regexp(type,'[e]'); xfield = [upper(type(1:espot)) type(espot+1:end) 'X']; yfield = [upper(type(1:espot)) type(espot+1:end) 'Y']; -if DATA.Silent - return; -end; +%Find active panels in type +panels = find(DATA.ViewPanels>0); + +%Remove the current panel from panels as we dont want to plot intersections with +%oneself +panels = panels(panels ~= panel); + +%no panels then return +if isempty(panels) + return +end + +%find nos with segmentation in the current timeframe t if no segmentation +%return from function + +%first we find the nophase +nophase = SET(no).TimeVector(t)/SET(no).TimeVector(end); + + +%find panels with nos that have segmentation +% ind = cellfun(@(x,y)~isempty(x) ,{SET(DATA.ViewPanels(panels)).(xfield)}); +ind = (~cellfun('isempty' ,{SET(DATA.ViewPanels(panels)).(xfield)})); + +if isempty(ind) || all(ind==0) + return +end + +%get the nos from the panels +noswithseg = DATA.ViewPanels(panels(ind)); + +if ~isnan(nophase) && t~=1 + TV_tmp = nan(length(noswithseg),max([SET(noswithseg).TSize])); + for i = 1:length(noswithseg) + TV_tmp(i,1:SET(noswithseg(i)).TSize) = SET(noswithseg(i)).TimeVector; + end + denomntr = [SET(noswithseg).TSize]-1; + if any(denomntr == 0) + % if denominator can be 0, then set time frames to 1 + tfs = ones(1,length(noswithseg)); + else + %Then we find the matching phases in the other nos + [~,tfs] = min((TV_tmp./([SET(noswithseg).TIncr].*(denomntr))'-nophase)'.^2); + %min((vertcat(SET(noswithseg).TimeVector)./([SET(noswithseg).TIncr].*([SET(noswithseg).TSize]-1))'-nophase)'.^2); + end + %check which slices there exists segmentation in the matching timeframes + nosz = cell(1,length(tfs)); + + for i = 1:length(noswithseg) + nosz{i} = find(~any(isnan(squeeze(SET(noswithseg(i)).(xfield)(:,tfs(i),:))))); + end +else + nosz = cell(1,length(t)); + for i = 1:length(noswithseg) + nosz{i} = find(~any(isnan(squeeze(SET(noswithseg(i)).(xfield)(:,t,:))))); + end +end + +%If there where no slices with segmentation in that timeframe remove +%them from noswithseg +ind = cellfun(@isempty,nosz); +noswithseg(ind) = []; +nosz(ind) = []; + +if ~isnan(nophase) && t~=1 + tfs(ind) = []; +end +%if no noswithseg return +if isempty(noswithseg) + return +end + +%Find equation for no plane using the position we find if image planes +%intersect +if ~ismember(viewtype,{'hla','vla','gla'}) + [pos,~,~,zdir] = calcfunctions('getimageposandorientation',no,SET(no).CurrentSlice,viewtype); +else + [pos,~,~,zdir] = calcfunctions('getimageposandorientation',no,SET(no).(upper(viewtype)).slice,viewtype); + if strcmp(viewtype,'gla') + ang = SET(no).GLA.angle; + res = SET(no).ResolutionY*cos(ang)+SET(no).ResolutionX*abs(sin(ang)); + end +end + +d = sum(pos.*zdir); + +%For each no with seg calculate intersection with the current plane +xbuild = []; +ybuild = []; +for loop = 1:length(noswithseg) + if ~isnan(nophase) && t~=1 + x = squeeze(SET(noswithseg(loop)).(xfield)(:,tfs(loop),nosz{loop})); + y = squeeze(SET(noswithseg(loop)).(yfield)(:,tfs(loop),nosz{loop})); + else + x = squeeze(SET(noswithseg(loop)).(xfield)(:,1,nosz{loop})); + y = squeeze(SET(noswithseg(loop)).(yfield)(:,1,nosz{loop})); + end + z = repmat(nosz{loop},size(x,1),1); + + pos = calcfunctions('xyz2rlapfh',... + noswithseg(loop),... + x(:),... + y(:),... + z(:)); + + if ~isempty(pos) %pos may be empty from rotated stacks. + %Find crossings + disttoplane = pos*(zdir')-d; + calcdist = (disttoplane(1:(end-1)).*disttoplane(2:end)); + ind = find(and(calcdist<0,abs(round(calcdist,4))>0.0000)); + + if ~isempty(ind) + crosspos = 0.5*(pos(ind,:)+pos(ind+1,:)); + + xyzno = calcfunctions('rlapfh2xyz',no,crosspos(:,1),crosspos(:,2),crosspos(:,3)); + + switch viewtype + case 'hla' + xbuild = [xbuild xyzno(3,:)]; %#ok + ybuild = [ybuild xyzno(2,:)]; %#ok + case 'vla' + xbuild = [xbuild xyzno(3,:)]; %#ok + ybuild = [ybuild xyzno(1,:)]; %#ok + case 'gla' + xbuild = [xbuild xyzno(3,:)]; %#ok + [~,glay] = sax2gla(xyzno(1,:),xyzno(2,:),0,noswithseg(loop)); + ybuild = [ybuild glay]; %#ok + otherwise + xbuild = [xbuild xyzno(1,:)]; %#ok + ybuild = [ybuild xyzno(2,:)]; %#ok + end + end + end + +end + +if ~isempty(xbuild) + xout = xbuild; + yout = ybuild; +end + +%--------------------------------------------------------------------- +function [xout,yout] = calcsegmentationintersections2(no,type,t,viewtype) %#ok +%--------------------------------------------------------------------- +%Calculates intersections between segmentation in image stacks. +%no is image stack and type is endo or epi, can also be rvendo etc. +%the type is a string that dynamically calls a field of the SET struct. + +global DATA SET + +%Always return something +xout = nan; +yout = nan; +espot = regexp(type,'[e]'); +xfield = [upper(type(1:espot)) type(espot+1:end) 'X']; +yfield = [upper(type(1:espot)) type(espot+1:end) 'Y']; %Find existing segmentation panelix = find(DATA.ViewPanels>0); @@ -1279,22 +1597,22 @@ function volume_helper(no) noloop = DATA.ViewPanels(loop); if ~isempty(SET(noloop).(xfield)) noseg(loop) = noloop; - typeseg{loop} = DATA.ViewPanelsType{loop}; + typeseg{loop} = 'one';%DATA.ViewPanelsType{loop}; %break %This causes segmentation from only one stack to be displayed - end; -end; + end +end typeseg = typeseg(noseg>0); noseg = noseg(noseg>0); if length(noseg)<1 return; -end; - +end + %Find equation for no plane if ~ismember(viewtype,{'hla','vla','gla'}) - [pos,~,~,zdir] = getimageposandorientation(no,SET(no).CurrentSlice,viewtype); + [pos,~,~,zdir] = calcfunctions('getimageposandorientation',no,SET(no).CurrentSlice,viewtype); else - [pos,~,~,zdir] = getimageposandorientation(no,SET(no).(upper(viewtype)).slice,viewtype); + [pos,~,~,zdir] = calcfunctions('getimageposandorientation',no,SET(no).(upper(viewtype)).slice,viewtype); if strcmp(viewtype,'gla') ang = SET(no).GLA.angle; res = SET(no).ResolutionY*cos(ang)+SET(no).ResolutionX*abs(sin(ang)); @@ -1308,30 +1626,26 @@ function volume_helper(no) if ~isequal(noseg(loop),no) || ~isequal(typeseg{loop},viewtype) x = SET(noseg(loop)).(xfield); y = SET(noseg(loop)).(yfield); - + if ~isempty(x)% || any(findfunctions(['findslicewith',type,'all'],noseg(loop))) %calculate corresponding timeframe if SET(no).TSize == 2 - if SET(no).CurrentTimeFrame == SET(noseg(loop)).CurrentTimeFrame - tfs = SET(no).CurrentTimeFrame; + if t == SET(noseg(loop)).CurrentTimeFrame + tfs = t; else tfs = []; tfdiff = []; end - elseif any(findfunctions(['findslicewith',type,'all'],noseg(loop))) + elseif any(findfunctions(['findslicewith',type,'all'],noseg(loop))) alltf = (1+((1:40)-1)/(SET(noseg(loop)).TSize-1)*(SET(no).TSize-1)); - [~,closestsegind] = min(abs(SET(no).CurrentTimeFrame-round(alltf))); + [~,closestsegind] = min(abs(t-round(alltf))); tfs = max(1,min(SET(noseg(loop)).TSize,closestsegind)); - tfdiff = abs(alltf(tfs)-SET(no).CurrentTimeFrame); + tfdiff = abs(alltf(tfs)-t); elseif SET(no).TSize>2 %find a corresponding (closest) tf in no, for each tf in noseg alltf = (1+((1:40)-1)/(SET(noseg(loop)).TSize-1)*(SET(no).TSize-1)); - tfs = max(1,min(SET(noseg(loop)).TSize,find(SET(no).CurrentTimeFrame==round(alltf)))); - tfdiff = abs(alltf(tfs)-SET(no).CurrentTimeFrame); -% tf = round(1+(SET(no).CurrentTimeFrame-1)/(SET(no).TSize-1)*(SET(noseg(loop)).TSize-1)); - %[~,tf] = min(abs(SET(noseg(loop)).TimeVector-SET(no).TimeVector(SET(no).CurrentTimeFrame))); - - % + tfs = max(1,min(SET(noseg(loop)).TSize,find(t==round(alltf)))); + tfdiff = abs(alltf(tfs)-t); else tfs = 1; end @@ -1361,16 +1675,16 @@ function volume_helper(no) end end end - + if ~isempty(pos) %pos may be empty from rotated stacks. %Find crossings disttoplane = pos*(zdir')-d; ind = find((disttoplane(1:(end-1)).*disttoplane(2:end))<0); - + if ~isempty(ind) crosspos = 0.5*(pos(ind,:)+pos(ind+1,:)); - - xyzno = rlapfh2xyz(no,crosspos(:,1),crosspos(:,2),crosspos(:,3)); + + xyzno = calcfunctions('rlapfh2xyz',no,crosspos(:,1),crosspos(:,2),crosspos(:,3)); switch viewtype case 'hla' @@ -1387,18 +1701,18 @@ function volume_helper(no) xbuild = [xbuild xyzno(1,:)]; %#ok ybuild = [ybuild xyzno(2,:)]; %#ok end - end; - end; + end + end - end; %empty slice - end; %zloop + end %empty slice + end %zloop if ~isempty(xbuild) xout = xbuild; yout = ybuild; end - end; %empty segmentation - end; %equal segmation -end; + end %empty segmentation + end %equal segmation +end %-------------------------------------------------------------------- function [x,y] = calcplaneintersections(NO,no,TYPE,type,slice,hslice) %#ok @@ -1418,10 +1732,10 @@ function volume_helper(no) if isequal(no,0) return; -end; +end if isequal(NO,0) return; -end; +end if nargin < 5 slice = SET(no).CurrentSlice; @@ -1430,6 +1744,20 @@ function volume_helper(no) TYPE = 'one'; type = 'one'; end +if isempty(type) + if not(isempty(TYPE)) + type = TYPE; + else + type = 'one'; + end +end +if isempty(TYPE) + if not(isempty(type)) + TYPE = type; + else + TYPE = 'one'; + end +end xszNO = SET(NO).XSize; xresNO = SET(NO).ResolutionX; @@ -1460,14 +1788,14 @@ function volume_helper(no) glaangle = SET(NO).GLA.angle; res = SET(NO).ResolutionY*cos(glaangle)+SET(NO).ResolutionX*abs(sin(glaangle)); yszNO = floor(SET(NO).YSize*abs(cos(glaangle))+SET(NO).XSize*abs(sin(glaangle))); - yresNO = res; + yresNO = res; end -% if strcmp(type,'vla') -% xszNO = SET(NO).YSize; -% xresNO = SET(NO).ResolutionY; -% yszNO = SET(NO).ZSize; -% yresNO = SET(NO).SliceThickness + SET(NO).SliceGap; -% end + % if strcmp(type,'vla') + % xszNO = SET(NO).YSize; + % xresNO = SET(NO).ResolutionY; + % yszNO = SET(NO).ZSize; + % yresNO = SET(NO).SliceThickness + SET(NO).SliceGap; + % end [posNO,xdirNO,ydirNO] = getimageposandorientation(NO,hslice,TYPE(1:3)); end @@ -1483,15 +1811,15 @@ function volume_helper(no) % +--- lc ---+ ladir = ydirNO; -lapos = posNO; +lapos = posNO; maxka = (yszNO-1)*yresNO; %in mm lbdir = xdirNO; -lbpos = posNO; +lbpos = posNO; maxkb = (xszNO-1)*xresNO; lcdir = ydirNO; -lcpos = posNO+xdirNO*(xszNO-1)*xresNO; +lcpos = posNO+xdirNO*(xszNO-1)*xresNO; maxkc = (yszNO-1)*yresNO; lddir = xdirNO; @@ -1516,13 +1844,13 @@ function volume_helper(no) ka = -pa/qa; else ka = NaN; -end; +end if ka<0 ka = NaN; -end; +end if ka>maxka ka = NaN; -end; +end %Line b qb = lbdir*(zdirno'); @@ -1531,13 +1859,13 @@ function volume_helper(no) kb = -pb/qb; else kb = NaN; -end; +end if kb<0 kb = NaN; -end; +end if kb>maxkb kb = NaN; -end; +end %Line c qc = lcdir*(zdirno'); @@ -1546,13 +1874,13 @@ function volume_helper(no) kc = -pc/qc; else kc = NaN; -end; +end if kc<0 kc = NaN; -end; +end if kc>maxkc kc = NaN; -end; +end %Line d qd = lddir*(zdirno'); @@ -1561,13 +1889,13 @@ function volume_helper(no) kd = -pd/qd; else kd = NaN; -end; +end if kd<0 kd = NaN; -end; +end if kd>maxkd kd = NaN; -end; +end % zeropos % +- => ka --+ => ImageOrientation(1:3) @@ -1596,13 +1924,13 @@ function volume_helper(no) global SET -if isequal(no,0); - no = 1; -end; +if isequal(no,0) + no = 1; +end if nargin<2 z = SET(no).ZSize; -end; +end switch z case 1 @@ -1621,12 +1949,12 @@ function volume_helper(no) otherwise rows = round(sqrt(z)); cols = ceil(z/rows); -end; +end %------------------------------------------------- function [xofs,yofs] = calcoffset(z,type,no,panel) %------------------------------------------------- -%Calculate offset required to plot coordinates in viewing +%Calculate offset required to plot coordinates in viewing %mode specified by type. global DATA SET NO @@ -1639,14 +1967,14 @@ function volume_helper(no) end if nargin<2 || isempty(type) type = DATA.ViewPanelsType{panel}; -end; +end if panel > numel(DATA.ViewPanelsMatrix) || ... isempty(DATA.ViewPanelsMatrix{panel}) [rows,cols] = calcrowscols(no); DATA.ViewPanelsMatrix{panel}(1) = rows; DATA.ViewPanelsMatrix{panel}(2) = cols; -end; +end switch type case {'montage','montagerow','montagefit'} @@ -1672,10 +2000,10 @@ function volume_helper(no) case 'montagesegmented' slicestoinclude = segment_main('getmontagesegmentedslices',no); if ismember(z,slicestoinclude) - c = 1+mod(z-slicestoinclude(1),DATA.ViewPanelsMatrix{panel}(2)); - r = ceil((z-slicestoinclude(1)+1)/DATA.ViewPanelsMatrix{panel}(2)); - yofs = (c-1)*SET(no).YSize; - xofs = (r-1)*SET(no).XSize; + c = 1+mod(z-slicestoinclude(1),DATA.ViewPanelsMatrix{panel}(2)); + r = ceil((z-slicestoinclude(1)+1)/DATA.ViewPanelsMatrix{panel}(2)); + yofs = (c-1)*SET(no).YSize; + xofs = (r-1)*SET(no).XSize; else yofs = nan; xofs = nan; @@ -1683,13 +2011,12 @@ function volume_helper(no) otherwise xofs = 0; yofs = 0; -end; +end %------------------------------------------------------ function [cellx,celly] = calcoffsetcells(no,panel,type) %#ok %------------------------------------------------------ -%Same as calculateoffset, but returns cells, used in -%updatemodeldisplay. +%Same as calculateoffset, but returns cells, used in global DATA SET NO if nargin < 2 @@ -1697,7 +2024,7 @@ function volume_helper(no) end if nargin==0 no = NO; -end; +end if nargin < 3 type = DATA.ViewPanelsType{panel}; end @@ -1751,7 +2078,7 @@ function volume_helper(no) otherwise cellx = num2cell(zeros(SET(no).ZSize,1)); celly = num2cell(zeros(SET(no).ZSize,1)); -end; +end %------------------------------------------------- @@ -1766,7 +2093,7 @@ function volume_helper(no) spacedist = sqrt(... ((SET(no).Mmode.Lx*SET(no).Mmode.M1-SET(no).Mmode.Lx*SET(no).Mmode.M2)*SET(no).ResolutionY).^2+... ((SET(no).Mmode.Ly*SET(no).Mmode.M1-SET(no).Mmode.Ly*SET(no).Mmode.M2)*SET(no).ResolutionX).^2); - + if ~isrectilinear(SET(no).TimeVector) timedist = abs(... SET(no).TimeVector(round(SET(no).Mmode.T1))-... @@ -1786,7 +2113,7 @@ function volume_helper(no) %DATA.DATASETPREVIEW. Size of the thumbnails is given by %DATA.GUISettings.ThumbnailSize. It is stored as a RGB image. -global DATA SET +global DATA SET %Reserve memory DATA.DATASETPREVIEW = repmat(uint8(0),... @@ -1808,19 +2135,19 @@ function volume_helper(no) % zero padding, elegantly done, no? :) /JU sz=size(tempim); tempim=padarray(tempim,round((length(tempim)-sz(1:2))/2)); - + tempim = imresize(tempim,DATA.GUISettings.ThumbnailSize*[1 1],'bilinear'); - + %Downsample -% xind = round(linspace(1,size(tempim,1),64)); -% yind = round(linspace(1,size(tempim,2),64)); -% tempim = tempim(xind,:); -% tempim = tempim(:,yind); + % xind = round(linspace(1,size(tempim,1),64)); + % yind = round(linspace(1,size(tempim,2),64)); + % tempim = tempim(xind,:); + % tempim = tempim(:,yind); %Store, vertically DATA.DATASETPREVIEW((noloop-1)*DATA.GUISettings.ThumbnailSize+(1:DATA.GUISettings.ThumbnailSize),:,:) = tempim; -end; +end %---------------------------------------------------------- function [outim,slicestoinclude] = calcmontageviewim(no,matrix,segmentedonly,cmap,c,b,im,tfs,oneextraslice,slices) %#ok @@ -1834,7 +2161,7 @@ function volume_helper(no) matrix = [rows cols]; end -if nargin < 3 +if nargin < 3 || isempty(segmentedonly) segmentedonly = false; end @@ -1844,63 +2171,57 @@ function volume_helper(no) if nargin < 8 || isempty(tfs) tfs = 1:SET(no).TSize; end + +%Set number of timeframes +TSize = length(tfs); + if nargin < 9 || isempty(oneextraslice) oneextraslice = true; end %Decide which slices to view if nargin < 10 || isempty(slices) -if segmentedonly %and currentslice - slicestoinclude = segment('getmontagesegmentedslices',no); -% slicestoincludeendo = find(findfunctions('findslicewithendo',no,tfs))'; -% slicestoincludeepi = find(findfunctions('findslicewithepi',no,tfs))'; -% slicestoincludervendo = find(findfunctions('findslicewithrvendo',no,tfs))'; -% slicestoinclude = unique([slicestoincludeendo slicestoincludeepi slicestoincludervendo]); -% if min(slicestoinclude) > 1 && oneextraslice -% slicestoinclude = [min(slicestoinclude)-1 slicestoinclude]; -% end -% if max(slicestoinclude) < SET(no).ZSize && oneextraslice -% slicestoinclude = [slicestoinclude max(slicestoinclude)+1]; -% end -else - slicestoinclude = 1:SET(no).ZSize; -end + if segmentedonly %and currentslice + slicestoinclude = segment('getmontagesegmentedslices',no); + else + slicestoinclude = 1:SET(no).ZSize; + end else slicestoinclude = slices; end %Add papillary visualization -stateandicon=segment('iconson','hidelv'); +stateandicon=viewfunctions('iconson','hidelv'); if not(stateandicon{1}) %not(isempty(SET(no).PapillaryIM)) && isequal(get(DATA.Handles.hidepapicon,'state'),'off') im(SET(no).PapillaryIM)=DATA.GUISettings.PapilarColor; end %Create space -if nargin >= 6 && ~isempty(cmap) && ~isempty(c) && ~isempty(b) - outim = repmat(uint8(0),[SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) SET(no).TSize 3]); +if nargin >= 6 && ~isempty(cmap) && ~isempty(c) && ~isempty(b) + outim = repmat(uint8(0),[SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) TSize 3]); elseif isempty(SET(no).Colormap) - outim = repmat(uint8(0),[SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) SET(no).TSize]); + outim = repmat(uint8(0),[SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) TSize]); else - outim = repmat(uint8(0),[SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) SET(no).TSize 3]); + outim = repmat(uint8(0),[SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) TSize 3]); end -for tloop=1:SET(no).TSize +for tloop=1:TSize for i=1:numel(slicestoinclude) zloop = slicestoinclude(i); col = 1+mod(i-1,matrix(2)); r = ceil(i/matrix(2)); - if nargin >= 6 && ~isempty(cmap) && ~isempty(c) && ~isempty(b) + if nargin >= 6 && ~isempty(cmap) && ~isempty(c) && ~isempty(b) outim(... (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... - (1+(col-1)*SET(no).YSize):(col*SET(no).YSize),tloop,:) = remapuint8( ... - im(:,:,tloop,zloop),no,cmap,c,b); + (1+(col-1)*SET(no).YSize):(col*SET(no).YSize),tloop,:) = repmat(remapuint8( ... + im(:,:,tfs(tloop),zloop),no,cmap,c,b),[1,1,1,size(outim,4)]); else outim(... (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... (1+(col-1)*SET(no).YSize):(col*SET(no).YSize),tloop,:) = remapuint8( ... - im(:,:,tloop,zloop),no); + im(:,:,tfs(tloop),zloop),no); end - end; -end; + end +end %-------------------------------------------------------------------------- function [linex,liney] = calcmontageviewline(no,matrix,inputx,inputy,tf,segmentedonly,tfs,oneextraslice) %#ok @@ -2005,7 +2326,7 @@ function volume_helper(no) % Remap according to indexed grayscape % Unless: % An external colormap has been supplied, then use that. -% This is used to force truecolor grayscale, by passing +% This is used to force truecolor grayscale, by passing % true to RETURNMAPPING. % c,b are contrast/brightness settings, used by contrast_Callback when % doing realtime update during mouse motion. @@ -2035,7 +2356,7 @@ function volume_helper(no) b = SET(no).IntensityMapping.Brightness; if isempty(c) c = SET(SET(no).Parent).IntensityMapping.Contrast; - b = SET(SET(no).Parent).IntensityMapping.Brightness; + b = SET(SET(no).Parent).IntensityMapping.Brightness; end end @@ -2054,7 +2375,7 @@ function volume_helper(no) end if isempty(d) - d=1; + d=1; end if d<0.1 @@ -2070,59 +2391,59 @@ function volume_helper(no) sz = [size(im,1) size(im,2) size(im,3) size(im,4)]; if isa(im,'single')||isa(im,'double') %im = c*im(:)+(b-0.5); -% try -if d~=1 - try - im = c.*nthroot(im(:),d)+b-0.5; - catch + % try + if d~=1 + try + im = c.*nthroot(im(:),d)+b-0.5; + catch + im = c.*im(:)+b-0.5; + end + else im = c.*im(:)+b-0.5; - end -else - im = c.*im(:)+b-0.5; -end%c*255.*(im(:)./255+b-0.5).^(1./d); -% catch -% %first lift im so that it is between 0 and 1 -% im=abs(min(im(:)))+im; -% im = c.*nthroot(im(:),d)+b-0.5;%c*255.*(im(:)./255+b-0.5).^(1./d); -% end + end%c*255.*(im(:)./255+b-0.5).^(1./d); + % catch + % %first lift im so that it is between 0 and 1 + % im=abs(min(im(:)))+im; + % im = c.*nthroot(im(:),d)+b-0.5;%c*255.*(im(:)./255+b-0.5).^(1./d); + % end z = max(min(round(cmax*im),cmax),cmin); -elseif isa(im,'int16'), +elseif isa(im,'int16') if ~isfield(SET(no),'minValue')||isempty(SET(no).minValue)||... ~isfield(SET(no),'maxValue')||isempty(SET(no).maxValue) SET(no).minValue = single(min(SET(no).IM(:))); SET(no).maxValue = single(max(SET(no).IM(:))); end - mi = SET(no).minValue; - ma = SET(no).maxValue; - - im = single(im(:)); - %im=c*im+(b-0.5);%TODO: should scale - - z = floor((im-mi)/(ma-mi)*cmax); - if d~=1 - z = uint8(c.*nthroot(z(:),d)+b-0.5)+1;%uint8(c*z+(b-0.5)*256)+1; % - else - z = uint8(c.*z(:)+b-0.5)+1; - end; - %z = max(min(round(c*z+(b-0.5)),cmax),cmin); + mi = SET(no).minValue; + ma = SET(no).maxValue; + + im = single(im(:)); + %im=c*im+(b-0.5);%TODO: should scale + + z = floor((im-mi)/(ma-mi)*cmax); + if d~=1 + z = uint8(single(c).*nthroot(z(:),d)+single(b)-0.5)+1;%uint8(c*z+(b-0.5)*256)+1; % + else + z = uint8(single(c).*z(:)+single(b)-0.5)+1; + end + %z = max(min(round(c*z+(b-0.5)),cmax),cmin); else myfailed(dprintf('Segment does not (yet) support type:%s',class(im))); return; end if (size(cmap,2) == 3) - % Extract r,g,b components - z3 = repmat(uint8(0),[size(z) 3]); - z3(:,1) = cmap(z,1); - z3(:,2) = cmap(z,2); - z3(:,3) = cmap(z,3); - z = reshape(z3,[sz 3]); + % Extract r,g,b components + z3 = repmat(uint8(0),[size(z) 3]); + z3(:,1) = cmap(z,1); + z3(:,2) = cmap(z,2); + z3(:,3) = cmap(z,3); + z = reshape(z3,[sz 3]); else - %Index color - z3 = repmat(uint8(0),size(z)); - z3(:) = cmap(z(:),1); - z = reshape(z3,sz); + %Index color + z3 = repmat(uint8(0),size(z)); + z3(:) = cmap(z(:),1); + z = reshape(z3,sz); end %------------------------------------------------------------------- @@ -2130,7 +2451,7 @@ function volume_helper(no) %------------------------------------------------------------------- %General helper fcn to resample a closed curve. if nargin<4 - method='linear';%used to be linear* + method='linear';%used to be linear* distributed = 'same'; end if nargin < 5 @@ -2144,7 +2465,7 @@ function volume_helper(no) ynew = interp1(y,linspace(1,size(y,1),n),method); case 'evenly' - %Remve duplicate points + %Remve duplicate points d = [0;cumsum(sqrt(diff(x).^2+diff(y).^2))]; ind = [1;diff(d)]>1e-3; uniquex = x(ind); @@ -2181,17 +2502,17 @@ function volume_helper(no) %to different number of points (n). if nargin<4 - method='linear';%used to be linear* + method='linear';%used to be linear* distributed = 'same'; end -if nargin < 5 +if nargin < 5 distributed = 'same'; end xnew = nan(n,size(x,2),size(x,3)); ynew = xnew; -for zloop=1:size(x,3) +for zloop=1:size(x,3) for tloop=1:size(x,2) if not(isnan(x(1,tloop,zloop))) [tempx,tempy] = resampleclosedcurve(... @@ -2200,16 +2521,16 @@ function volume_helper(no) xnew(:,tloop,zloop) = tempx; ynew(:,tloop,zloop) = tempy; end - end; -end; + end +end + - %-------------------------------------------------------------------------- function [meanint,defectextent,varargout] = calcintensityanddefect(im,... tf,numpoints,numsectors,nprofiles,pos, ... no,endox,endoy,epix,epiy,sz,resolution,defect,numwidth,timeresolved) %#ok %-------------------------------------------------------------------------- -%Calculates the mean intensity within sectors as a preperation to +%Calculates the mean intensity within sectors as a preperation to %generate a bullseye plot. % %-im image @@ -2222,7 +2543,7 @@ function volume_helper(no) %sz: size of image stack %resolution: resolution of image stack %defect: (EH: I do not know what it is, works if empty) -%numwidth: specify if it should calculate several sectors across +%numwidth: specify if it should calculate several sectors across % wallthickness. If a scalar it % specifices the number of % layers in the myocardium. If a @@ -2251,13 +2572,13 @@ function volume_helper(no) numslices = length(pos); meanint = zeros(numsectors,numslices); -%Added EH: If numwidth is a vector then it is interpreted as +%Added EH: If numwidth is a vector then it is interpreted as %[perencentendo percent epi]. if length(numwidth)>1 numlayers = length(numwidth)-1; else numlayers = numwidth; -end; +end %Check if we should return the mask and the sectors if nargout>2 @@ -2265,13 +2586,13 @@ function volume_helper(no) maskcell = cell(numslices,numsectors,numlayers); else storemask = false; -end; +end if nargout>3 storesector = true; sectorcell = cell(numslices,numsectors,numlayers,2); else storesector = false; -end; +end %Upsample model if not(nprofiles == size(endox,1)) @@ -2282,14 +2603,14 @@ function volume_helper(no) mask = zeros(sz(1),sz(2)); defectextent = zeros(numsectors,numslices); for sloop = 1:numslices - if not(isnan(epix(1,tf,pos(sloop)))) - + if not(isempty(epix)) && not(isnan(epix(1,tf,pos(sloop)))) + %Find sectors [~,~,episectors] = findmeaninsectorslice('epi',numpoints,tf,pos(sloop),numsectors,no, ... endox(:,tf,pos(sloop)),endoy(:,tf,pos(sloop)),epix(:,tf,pos(sloop)),epiy(:,tf,pos(sloop))); if not(isnan(endox(1,tf,pos(sloop)))) - [~,~,endosectors] = findmeaninsectorslice('endo',numpoints,tf,pos(sloop),numsectors,no, ... - endox(:,tf,pos(sloop)),endoy(:,tf,pos(sloop)),epix(:,tf,pos(sloop)),epiy(:,tf,pos(sloop))); + [~,~,endosectors] = findmeaninsectorslice('endo',numpoints,tf,pos(sloop),numsectors,no, ... + endox(:,tf,pos(sloop)),endoy(:,tf,pos(sloop)),epix(:,tf,pos(sloop)),epiy(:,tf,pos(sloop))); else endosectors = episectors; end @@ -2298,7 +2619,7 @@ function volume_helper(no) xdiffslice = abs(endox(:,tf,pos(sloop))-epix(:,tf,pos(sloop))); ydiffslice = abs(endoy(:,tf,pos(sloop))-epiy(:,tf,pos(sloop))); wallthicknessinslice = mean(sqrt((xdiffslice*resolution(1)).^2+(ydiffslice*resolution(2)).^2)); - + N = nprofiles; for loop=1:numsectors if episectors(loop) +warning off; for tloop=1:numtf for zloop=1:nslices for loop=1:numsectors @@ -2646,27 +2967,27 @@ function volume_helper(no) idx = [... sectors(loop,zloop,tloop):(numpoints-1) ... 1:sectors(loop+1,zloop,tloop)]; - end; + end res(loop,zloop,tloop) = mean(inp(idx,tloop,pos(zloop))); maxres(loop,zloop,tloop) = max(inp(idx,tloop,pos(zloop))); - end; - end; -end; + end + end +end warning(warnstat); varargout = cell(1,nargout-1); if nargout>=2 varargout{1} = meanx; -end; +end if nargout>=3 varargout{2} = meany; -end; +end if nargout>=4 varargout{3} = sectors; -end; +end if nargout>=5 varargout{4} = maxres; -end; +end %-------------------------------------------------------------------------- function [varargout] = findmeaninsectorslice(type,numpoints,tf,slice,... @@ -2679,11 +3000,11 @@ function volume_helper(no) if nargin<5 numsectors = 6; -end; +end if nargin<6 no = NO; -end; +end if nargin < 7 || (nargin==11 && isempty(endox)) if ~isempty(SET(no).EndoX) @@ -2710,7 +3031,7 @@ function volume_helper(no) isendo=1; else isendo=0; -end; +end %Upsample model if not(numpoints==DATA.NumPoints) @@ -2719,13 +3040,13 @@ function volume_helper(no) else endox = nan(numpoints,length(tf),length(slice)); endoy = endox; - end; + end if ~isempty(epix) [epix,epiy] = resamplemodel(epix,epiy,numpoints); else epix = nan(numpoints,length(tf),length(slice)); - epiy = epix; - end; + epiy = epix; + end end %Find center @@ -2735,7 +3056,7 @@ function volume_helper(no) else x = mean(epix); y = mean(epiy); -end; +end meanx = mean(x(:)); meany = mean(y(:)); @@ -2749,7 +3070,7 @@ function volume_helper(no) ang = angle(complex(... epiy(1:(end-1))-meany,... epix(1:(end-1))-meanx)); -end; +end ang = ang*180/pi; wantangles = linspace(-180,180,numsectors+1); wantangles = wantangles+rotation; @@ -2761,24 +3082,24 @@ function volume_helper(no) if trash2=1 varargout{1} = meanx; -end; +end if nargout>=2 varargout{2} = meany; -end; +end if nargout>=3 varargout{3} = sectors; -end; +end %----------------------------------------------------------------------- function [pos,xdir,ydir,zdir] = getimageposandorientation(no,slice,type) @@ -2790,9 +3111,9 @@ function volume_helper(no) if nargin < 3 type = 'one'; end -if nargin<2 +if nargin < 2 || isempty(slice) slice = SET(no).CurrentSlice; -end; +end if SET(no).Rotated %Rotated @@ -2800,18 +3121,18 @@ function volume_helper(no) rotdir = SET(no).ImageOrientation(4:6); r1dir = SET(no).ImageOrientation(1:3); r2dir = cross(rotdir,r1dir); - + %Calculate radius to center radius = SET(no).RotationCenter*SET(no).ResolutionY; - + %Calculate center of rotation center = pos+radius*r1dir; - + alpha = (pi/(SET(no).ZSize))*(slice-1); pos = center+(... radius*cos(alpha)*r1dir-... radius*sin(alpha)*r2dir); - + %Find orientation xdir = rotdir; ydir = -(pos-center); %new position - center of rotation @@ -2820,9 +3141,8 @@ function volume_helper(no) else %Normal cartesian coordinates xdir = SET(no).ImageOrientation(4:6); - ydir = SET(no).ImageOrientation(1:3); + ydir = SET(no).ImageOrientation(1:3); zdir = cross(ydir,xdir); - if strcmp(type,'hla') temp = xdir; @@ -2853,12 +3173,12 @@ function volume_helper(no) pos = SET(no).ImagePosition-... zdir*(SET(no).SliceThickness+SET(no).SliceGap)*(slice-1); -% %for multiple slices (future improvement) -% pos = repmat(SET(no).ImagePosition,length(slice),1)-... -% (diag(zdir*(SET(no).SliceThickness+SET(no).SliceGap))*repmat(slice-1,3,1))'; + % %for multiple slices (future improvement) + % pos = repmat(SET(no).ImagePosition,length(slice),1)-... + % (diag(zdir*(SET(no).SliceThickness+SET(no).SliceGap))*repmat(slice-1,3,1))'; end -end; +end %------------------------ function z = econvn(im,f) @@ -2868,24 +3188,24 @@ function volume_helper(no) case 4 z = im; if size(im,3)~=1 - for loop=1:size(im,4); + for loop=1:size(im,4) z(:,:,:,loop) = econv3(im(:,:,:,loop),f); - end; + end else - for loop=1:size(im,4); + for loop=1:size(im,4) z(:,:,1,loop) = conv2(im(:,:,:,loop),f,'same'); - end; - end; + end + end case 3 z = econv3(im,f); case 2 z = conv2(im,f,'same'); otherwise error('Number of dimensions not supported.'); -end; +end %--------------------------------------- -function [pos] = rlapfh2xyz(no,rl,ap,fh) +function [pos] = rlapfh2xyz(no,rl,ap,fh) %#ok %--------------------------------------- %Convert from RL,AP,FH coordinates to Segment internal coordinate system. global DATA SET @@ -2894,10 +3214,10 @@ function volume_helper(no) myfailed('Not yet implemented for rotated image stacks.',DATA.GUI.Segment); else xdir = SET(no).ImageOrientation(4:6)'; - ydir = SET(no).ImageOrientation(1:3)'; + ydir = SET(no).ImageOrientation(1:3)'; zdir = cross(... SET(no).ImageOrientation(1:3),... - SET(no).ImageOrientation(4:6))'; + SET(no).ImageOrientation(4:6))'; rl = rl(:)'-SET(no).ImagePosition(1); %Translate corner of box to 0,0,0 ap = ap(:)'-SET(no).ImagePosition(2); @@ -2906,31 +3226,32 @@ function volume_helper(no) pos = [xdir ydir -zdir]\[rl;ap;fh]; pos(1,:) = pos(1,:)/SET(no).ResolutionX+1; pos(2,:) = pos(2,:)/SET(no).ResolutionY+1; - pos(3,:) = pos(3,:)/(SET(no).SliceGap+SET(no).SliceThickness)+1; + pos(3,:) = pos(3,:)/(SET(no).SliceGap+SET(no).SliceThickness)+1; -end; +end %------------------------------------ function [pos] = xyz2rlapfh(no,x,y,z) %------------------------------------ %Converts from segment coordinate system to RL,AP,FH coordinate system. -global DATA SET +global SET if SET(no).Rotated pos = []; - myfailed('Not yet implemented for rotated image stacks.',DATA.GUI.Segment); + myfailed('Not yet implemented for rotated image stacks.')%,DATA.GUI.Segment); else zdir = cross(... SET(no).ImageOrientation(1:3),... - SET(no).ImageOrientation(4:6)); + SET(no).ImageOrientation(4:6)); + x = (x(:)-1)*SET(no).ResolutionX; y = (y(:)-1)*SET(no).ResolutionY; z = (z(:)-1)*(SET(no).SliceThickness+SET(no).SliceGap); - pos = repmat(SET(no).ImagePosition,length(x),1)+... - repmat(SET(no).ImageOrientation(4:6),length(x),1).*repmat(x,1,3)+... - repmat(SET(no).ImageOrientation(1:3),length(x),1).*repmat(y,1,3)-... %was minus - repmat(zdir,length(x),1).*repmat(z,1,3); -end; + pos = SET(no).ImagePosition +... + SET(no).ImageOrientation(4:6).*x+... + SET(no).ImageOrientation(1:3).*y-... %was minus + zdir.*z; +end %------------------------------------- function [impos,ormat] = calcormat(no) %#ok @@ -2948,7 +3269,7 @@ function volume_helper(no) cross(SET(no).ImageOrientation(4:6),SET(no).ImageOrientation(1:3))']; %------------------------------------------------------------------ -function [x,y,z] = cyl2cart(xin,yin,slice,numslices,rotationcenter) +function [x,y,z] = cyl2cart(xin,yin,slice,numslices,rotationcenter) %#ok %------------------------------------------------------------------ %Convert from cylindrical to cartesian coordinates @@ -2959,7 +3280,7 @@ function volume_helper(no) y = rad.*cos(angle)+rotationcenter; %-------------------------------------------------------- -function [window,level] = con2win(contrast,brightness,no) +function [window,level] = con2win(contrast,brightness,no) %#ok %-------------------------------------------------------- %Convert from contrast to window & level @@ -2984,7 +3305,7 @@ function volume_helper(no) end %-------------------------------------------------------- -function [contrast,brightness] = win2con(window,level,no) +function [contrast,brightness] = win2con(window,level,no) %#ok %-------------------------------------------------------- %Inverse of con2win @@ -3016,7 +3337,7 @@ function volume_helper(no) (xi-SET(no).GLA.x0)*sin(ang)*SET(no).ResolutionX); %----------------------------------- -function [x,y,z] = gla2sax(xi,yi,no) +function [x,y,z] = gla2sax(xi,yi,no) %#ok %----------------------------------- %Convert image coordinates from GLA to short-axis view global SET @@ -3026,11 +3347,10 @@ function volume_helper(no) x = SET(no).GLA.x0 + sin(SET(no).GLA.angle)*yi*res/SET(no).ResolutionX; y = SET(no).GLA.y0 + cos(SET(no).GLA.angle)*yi*res/SET(no).ResolutionY; - %------------------------------------------- -function [mantelarea, sliceMantelArea] = calcmantelarea(no) +function [mantelarea, sliceMantelArea] = calcmantelarea(no) %#ok %------------------------------------------- -%Calculate the mantel area in cm^2 of the LV endocardium in each timeframe. +%Calculate the mantel area in cm^2 of the LV endocardium in each timeframe. global SET if sum(findfunctions('findslicewithendo',no))==0 @@ -3054,6 +3374,90 @@ function volume_helper(no) sliceMantelArea=mantelarea'; mantelarea=sum(mantelarea,2)'; +%-------------------- +function calcflowinroi(no) %#ok +%-------------------- +%calculates flow from current ROI +global SET + +nom = SET(no).Flow.MagnitudeNo; +nop = SET(nom).Flow.PhaseNo; + +warnedempty = false; +outsize = [SET(nom).XSize SET(nom).YSize]; +roinbr = SET(nom).RoiCurrent; + +if length(SET(nom).Roi(roinbr).T)==1 %For non-time resolved Phase Contrast images + SET(nom).TIncr=1; +end +mask = false([SET(nom).XSize SET(nom).YSize SET(nom).Roi(roinbr).T]); +%create mask for all time frames +for tloop = SET(nom).Roi(roinbr).T + %Create mask + tempmask = logical(segment('createmask',... + outsize,... + SET(nom).Roi(roinbr).Y(:,tloop),... + SET(nom).Roi(roinbr).X(:,tloop))); + mask(:,:,tloop) = tempmask; +end +%Extract phase image +phasedata = SET(nop).IM(:,:,:,SET(nom).Roi(roinbr).Z); + +%If empty phasecorr, the do not add phase correction. +if isempty(SET(nop).Flow.PhaseCorr) + veldata = SET(nom).Roi(roinbr).Sign*... + (phasedata-0.5)*2*SET(nop).VENC; +else + %Phase correction + if SET(nop).Flow.PhaseCorrTimeResolved + %Time resolved phase correction + veldata = SET(nom).Roi(roinbr).Sign*... + (phasedata-0.5-SET(nop).Flow.PhaseCorr(:,:,:,SET(nom).Roi(roinbr).Z))*2*SET(nop).VENC; + else + %Stationary phase correction + phasecorr = squeeze(SET(nop).Flow.PhaseCorr(:,:,1,SET(nom).Roi(roinbr).Z)); + correctiondata = repmat(phasecorr,[1 1 SET(nom).Roi(roinbr).T 1]); + veldata = SET(nom).Roi(roinbr).Sign*... + (phasedata-0.5-correctiondata)*2*SET(nop).VENC; + end +end + +veldata = veldata(mask); +if isempty(veldata) + veldata = nan; + posveldata = nan; + negveldata = nan; +else + posveldata = veldata(veldata>0); + negveldata = veldata(veldata<0); +end + +SET(nom).Flow.Result(roinbr).velmean(:) = squeeze(mean(veldata,[1 2])); +SET(nom).Flow.Result(roinbr).velstd(:) = squeeze(std(veldata,0,[1 2])); +SET(nom).Flow.Result(roinbr).velmax(:) = squeeze(max(veldata,[],[1 2])); +SET(nom).Flow.Result(roinbr).velmin(:) = squeeze(min(veldata,[],[1 2])); +SET(nom).Flow.Result(roinbr).kenergy(:) = squeeze(sum((veldata/100).^3/2*(SET(nom).ResolutionX*SET(nom).ResolutionY/1e6)*1060, [1 2])); %kg/m^3 +SET(nom).Flow.Result(roinbr).area(:) = SET(nom).ResolutionX*SET(nom).ResolutionY*squeeze(sum(mask, [1 2]))/100; %cm^2 +% % SET(nom).Flow.Result(roinbr).netflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(veldata); %cm^3 +% % SET(nom).Flow.Result(roinbr).posflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(posveldata); %cm^3 +% % SET(nom).Flow.Result(roinbr).negflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(negveldata); %cm^3 + +%Add flow results to regular Roi areas +% % SET(nom).Roi(roinbr).Area = SET(nom).Flow.Result(roinbr).area; +% % +% % SET(nom).Flow.Result(roinbr).diameter = NaN; +% % hr = (60/(SET(nom).TSize*SET(nom).TIncr)); +% % +% % netflow = SET(nom).Flow.Result(roinbr).netflow; +% % timeframes = SET(nom).Roi(roinbr).T;%1:SET(nom).TSize; +% % TIncr = SET(nom).TIncr; +% % +% % %Sum +% % SET(nom).Flow.Result(roinbr).nettotvol = nansum(netflow(timeframes))*TIncr; +% % SET(nom).Flow.Result(roinbr).netforwardvol = nansum(netflow(timeframes).*(netflow(timeframes)>0))*TIncr; +% % SET(nom).Flow.Result(roinbr).netbackwardvol = nansum(netflow(timeframes).*(netflow(timeframes)<0))*TIncr; +% % SET(nom).Flow.Result(roinbr).regfrac = abs(100*SET(nom).Flow.Result(roinbr).netbackwardvol/SET(nom).Flow.Result(roinbr).netforwardvol); +% % SET(nom).Flow.Result(roinbr).sv = SET(nom).Flow.Result(roinbr).nettotvol/hr*60; %-------------------- function calcflow(no) %#ok @@ -3068,12 +3472,39 @@ function calcflow(no) %#ok warnedempty = false; outsize = [SET(nom).XSize SET(nom).YSize]; roinbr = SET(nom).RoiCurrent; +if isempty(roinbr) + myfailed('No ROIs available.',DATA.GUI.Segment); + return +end -if length(SET(nom).Roi(roinbr).T)==1 %For non-time resolved Phase Contrast images - SET(nom).TIncr=1; +if DATA.DoThisFrameOnly + tvec = SET(nom).CurrentTimeFrame; +else + tvec = SET(nom).Roi(roinbr).T; end -for tloop = SET(nom).Roi(roinbr).T +numtimeframes = length(SET(nom).Roi(roinbr).T); +if (numtimeframes - sum(isnan(SET(nom).Roi(roinbr).Mean))) == 1 %ROI is drawn in only one time frame + if numtimeframes == 1 %For non-time resolved Phase Contrast images + SET(nom).TIncr=1; %Continue to flow calculation based on only one time frame + else + %Skip flow calculation since the ROI is drawn in only one time frame + return + end +end +%initialize with NaN +% initvalues = nan(1,SET(nom).TSize); +% SET(nom).Flow.Result(roinbr).velmean = initvalues; +% SET(nom).Flow.Result(roinbr).velstd = initvalues; +% SET(nom).Flow.Result(roinbr).velmax = initvalues; +% SET(nom).Flow.Result(roinbr).velmin = initvalues; +% SET(nom).Flow.Result(roinbr).kenergy = initvalues; +% SET(nom).Flow.Result(roinbr).area = initvalues; +% SET(nom).Flow.Result(roinbr).netflow = initvalues; +% SET(nom).Flow.Result(roinbr).posflow = initvalues; +% SET(nom).Flow.Result(roinbr).negflow = initvalues; + +for tloop = tvec %Create mask mask = logical(segment('createmask',... outsize,... @@ -3097,35 +3528,50 @@ function calcflow(no) %#ok %Stationary phase correction veldata = SET(nom).Roi(roinbr).Sign*... (temp-0.5-SET(nop).Flow.PhaseCorr(:,:,1,SET(nom).Roi(roinbr).Z))*2*SET(nop).VENC; - end; - end; + end + end veldata = veldata(mask); if isempty(veldata) - if not(warnedempty) - mywarning('Empty ROI detected. Should not occur.',DATA.GUI.Segment); - end; - warnedempty = true; + veldata = nan; + posveldata = nan; + negveldata = nan; else posveldata = veldata(veldata>0); negveldata = veldata(veldata<0); - SET(nom).Flow.Result(roinbr).velmean(tloop) = mean(veldata); - SET(nom).Flow.Result(roinbr).velstd(tloop) = std(veldata); - SET(nom).Flow.Result(roinbr).velmax(tloop) = max(veldata); - SET(nom).Flow.Result(roinbr).velmin(tloop) = min(veldata); - SET(nom).Flow.Result(roinbr).kenergy(tloop) = sum((veldata/100).^3/2*(SET(nom).ResolutionX*SET(nom).ResolutionY/1e6)*1060); %kg/m^3 - SET(nom).Flow.Result(roinbr).area(tloop) = SET(nom).ResolutionX*SET(nom).ResolutionY*sum(mask(:))/100; %cm^2 - SET(nom).Flow.Result(roinbr).netflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(veldata); %cm^3 - SET(nom).Flow.Result(roinbr).posflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(posveldata); %cm^3 - SET(nom).Flow.Result(roinbr).negflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(negveldata); %cm^3 - end; -end; + end + % if isempty(veldata) + % if not(warnedempty) + % mywarning('Empty ROI detected. Should not occur.',DATA.GUI.Segment); + % end + % warnedempty = true; + % else + %posveldata = veldata(veldata>0); + %negveldata = veldata(veldata<0); + SET(nom).Flow.Result(roinbr).velmean(tloop) = mean(veldata); + SET(nom).Flow.Result(roinbr).velstd(tloop) = std(veldata); + SET(nom).Flow.Result(roinbr).velmax(tloop) = max(veldata); + SET(nom).Flow.Result(roinbr).velmin(tloop) = min(veldata); + SET(nom).Flow.Result(roinbr).kenergy(tloop) = sum((veldata/100).^3/2*(SET(nom).ResolutionX*SET(nom).ResolutionY/1e6)*1060); %kg/m^3 + SET(nom).Flow.Result(roinbr).area(tloop) = SET(nom).ResolutionX*SET(nom).ResolutionY*sum(mask(:))/100; %cm^2 + SET(nom).Flow.Result(roinbr).netflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(veldata); %cm^3 + SET(nom).Flow.Result(roinbr).posflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(posveldata); %cm^3 + SET(nom).Flow.Result(roinbr).negflow(tloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(negveldata); %cm^3 + % end + %Add flow results to regular Roi areas + SET(nom).Roi(roinbr).Area(tloop) = SET(nom).Flow.Result(roinbr).area(tloop); +end + +% %Add flow results to regular Roi areas +% SET(nom).Roi(roinbr).Area = SET(nom).Flow.Result(roinbr).area; + SET(nom).Flow.Result(roinbr).diameter = NaN; hr = (60/(SET(nom).TSize*SET(nom).TIncr)); netflow = SET(nom).Flow.Result(roinbr).netflow; timeframes = SET(nom).Roi(roinbr).T;%1:SET(nom).TSize; TIncr = SET(nom).TIncr; + %Sum SET(nom).Flow.Result(roinbr).nettotvol = nansum(netflow(timeframes))*TIncr; SET(nom).Flow.Result(roinbr).netforwardvol = nansum(netflow(timeframes).*(netflow(timeframes)>0))*TIncr; @@ -3151,7 +3597,9 @@ function clearflow(no,roinbr) %#ok if length(SET(no).Flow.Result) == 1 clearallflow(no); else - SET(no).Flow.Result(roinbr) = []; + if ~(length(SET(no).Flow.Result)< roinbr) + SET(no).Flow.Result(roinbr) = []; + end end end end @@ -3159,7 +3607,7 @@ function clearflow(no,roinbr) %#ok %------------------------ -function clearallflow(no) +function clearallflow(no) %------------------------ %clear all ROI flow from no global SET @@ -3171,3 +3619,502 @@ function clearallflow(no) if ~isempty(SET(no).Flow) SET(no).Flow.Result = []; end + +%------------------------------------------- +function varargout = calclvvolumeAVPD(no,docomp) +%------------------------------------------- +% this function is the old version of calclvvolume that is used on github +% and is needed for AVPD calculation +%Calculate LV volume. Docomp if to use longaxis motion, see below. +%Uses area*(thickness+slicedist) +%NOTE: the exported LVM do NOT include Papillary volume (PV) + +global DATA SET + +if nargin<2 + docomp=true; +elseif SET(no).Longaxis > 1%SET(NO).Longaxis > 1 + docomp = true; +end + +if SET(no).Rotated + calclvvolumepolar(no); + return; +end + +ind = (findfunctions('findslicewithendo',no))|(findfunctions('findslicewithepi',no)); %Accepts empty endo and epi if exist + +if ~any(ind) + SET(no).LVV = nan(1,SET(no).TSize); + SET(no).EPV = SET(no).LVV; + SET(no).LVM = SET(no).LVV; + SET(no).PV = zeros(size(SET(no).LVV)); + SET(no).PFR = 0; + SET(no).PER = 0; + SET(no).PFRT = 1; + SET(no).PERT = 1; + SET(no).ESV = 0; + SET(no).EDV = 0; + SET(no).EF = 0; + SET(no).SV = 0; + if nargout>0 + varargout = cell(1,1); + varargout{1} = []; + end + if nargout>1 + varargout{2} = []; + end + return; +end + +%Find what slices to do +if SET(no).ZSize>1 + pos = find(ind); +else + pos = 1; +end +LVVall = zeros(length(pos),SET(no).TSize); +EPVall = zeros(length(pos),SET(no).TSize); + +% if isempty(SET(no).EndoX) +% %This far then create +% SET(no).EndoX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% SET(no).EndoY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% end; +% +% if isempty(SET(no).EpiX) +% %This far then create +% SET(no).EpiX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% SET(no).EpiY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); +% end; + +%Loop over all segmented slices +for sloop=1:length(pos) + for tloop=1:SET(no).TSize + if ~isempty(SET(no).EndoX)&&~isnan(SET(no).EndoX(1,tloop,pos(sloop))) + A = stablepolyarea(... + SET(no).ResolutionY*SET(no).EndoY(1:end-1,tloop,pos(sloop)),... + SET(no).ResolutionX*SET(no).EndoX(1:end-1,tloop,pos(sloop))); + LVVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; %to cm3 + end + if ~isempty(SET(no).EpiX)&&~isnan(SET(no).EpiX(1,tloop,pos(sloop))) + A = stablepolyarea(... + SET(no).ResolutionY*SET(no).EpiY(1:end-1,tloop,pos(sloop)),... + SET(no).ResolutionX*SET(no).EpiX(1:end-1,tloop,pos(sloop))); + EPVall(sloop,tloop)=A*(SET(no).SliceThickness+SET(no).SliceGap)/1000; %to cm3 + end + end +end + +%Sum to get total volume +if length(pos)>1 + SET(no).LVV = sum(LVVall); + SET(no).EPV = sum(EPVall); +else + SET(no).LVV = LVVall; + SET(no).EPV = EPVall; +end +SET(no).LVM = SET(no).EPV-SET(no).LVV+SET(no).PV; + +if nargout>0 + varargout = cell(1,1); + varargout{1} = LVVall; +end + +if nargout>1 + varargout{2} = EPVall; +end + +if nargout>2 + varargout{3} = 1.05*(EPVall-LVVall); %LVM in g, NOTE not include Papillary volume (PV) +end + +%Update EDV,ESV +SET(no).EDV = SET(no).LVV(SET(no).EDT); +if ~isequal(SET(no).EDT,SET(no).EST) + SET(no).ESV = SET(no).LVV(SET(no).EST); +else + SET(no).ESV = NaN; +end + +if (SET(no).ZSize>2)&&docomp + LVVnocomp = SET(no).LVV; + EPVnocomp = SET(no).EPV; + + for rloop=1:1 %Converges very quickly + + %Calculate compensation mechanism + if (SET(no).LVV(SET(no).EDT)-SET(no).LVV(SET(no).EST)~=0) + pp = SET(no).LVV; + pp = pp-SET(no).LVV(SET(no).EST); + pp = pp./(SET(no).LVV(SET(no).EDT)-SET(no).LVV(SET(no).EST)); + pp = 1-pp; + pp = min(max(pp,0),1); + else + pp = ones(size(SET(no).LVV)); + end + err = zeros(1,20); + + %Compensate + %pp = pp.*pp; + + %Check if autodetect + if SET(no).AutoLongaxis + for loop=1:20 + + %Calculate slices + slices = (loop-1); %Convert to mm + slices = slices/(SET(no).SliceThickness+SET(no).SliceGap); %Convert to slices + + sloop=1; + SET(no).LVV = LVVnocomp; %Restore + SET(no).EPV = EPVnocomp; + while (slices>0)&&(sloop 1mm between, first is zero + slices = (SET(no).Longaxis-1); + if isempty(slices) + slices = 0; + end + slices = slices/(SET(no).SliceThickness+SET(no).SliceGap); + + %Compensate the last time, now store it! + sloop=1; + SET(no).LVV = LVVnocomp; %Restore + SET(no).EPV = EPVnocomp; + + %Check if need to fix with outline + if ~isempty(SET(no).EndoX) + zloop = find(not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,:)))); + elseif ~isempty(SET(no).EpiX) + zloop = find(not(isnan(SET(no).EpiX(1,SET(no).CurrentTimeFrame,:)))); + else + zloop = []; + end + if isempty(zloop) + slices = 0; + zloop = SET(no).CurrentSlice; + else + zloop = zloop(1); + end + + %Make sure that it is updated + %if docomp + % updatemodeldisplay; + %end; + + while (slices>0)&&(sloop<=size(LVVall,1)) + %Remove whole slice or fraction of it. + SET(no).LVV = SET(no).LVV-min(slices,1)*LVVall(sloop,:).*pp; + SET(no).EPV = SET(no).EPV-min(slices,1)*EPVall(sloop,:).*pp; + + [xofs,yofs] = calcoffset(zloop,'montage'); + + %Need to fix with outline? + if 0%get(DATA.Handles.volumeoutlinecheckbox,'value') + for tloop=1:SET(no).TSize + if ~isempty(SET(no).EndoX) + SET(no).EndoXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + (SET(no).EndoX(:,tloop,zloop)-SET(no).CenterX)*(1-pp(tloop)*min(1,slices))+SET(no).CenterX+xofs; + SET(no).EndoYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + (SET(no).EndoY(:,tloop,zloop)-SET(no).CenterY)*(1-pp(tloop)*min(1,slices))+SET(no).CenterY+yofs; + end + if ~isempty(SET(no).EpiX) + SET(no).EpiXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + (SET(no).EpiX(:,tloop,zloop)-SET(no).CenterX)*(1-pp(tloop)*min(1,slices))+SET(no).CenterX+xofs; + SET(no).EpiYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + (SET(no).EpiY(:,tloop,zloop)-SET(no).CenterY)*(1-pp(tloop)*min(1,slices))+SET(no).CenterY+yofs; + end + end + else + for tloop=1:SET(no).TSize + if ~isempty(SET(no).EndoX) + SET(no).EndoXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + SET(no).EndoX(:,tloop,zloop)+xofs; + SET(no).EndoYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + SET(no).EndoY(:,tloop,zloop)+yofs; + end + if ~isempty(SET(no).EpiX) + SET(no).EpiXView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + SET(no).EpiX(:,tloop,zloop)+xofs; + SET(no).EpiYView((1+(zloop-1)*(DATA.NumPoints+1)):(zloop*(DATA.NumPoints+1)-1),tloop) = ... + SET(no).EpiY(:,tloop,zloop)+yofs; + end + end + end + zloop = zloop+1; + slices = slices-1; + sloop = sloop+1; + end + end %rloop + + if DATA.Silent + return; + end + + for loop=1:length(DATA.ViewPanels) + if isequal(no,DATA.ViewPanels(loop)) + if 0%isequal(get(DATA.Handles.volumeoutlinecheckbox,'value'),1) &&... + ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montage','montagerow','montagefit','sax3'}) + set(DATA.Handles.endocontour(loop),'LineStyle',':'); + set(DATA.Handles.epicontour(loop),'LineStyle',':'); + else + set(DATA.Handles.endocontour(loop),'LineStyle','-'); + set(DATA.Handles.epicontour(loop),'LineStyle','-'); + end + end + end + +end %If docompensation + +%------------------------------------------- +function [xofs,yofs] = calcoffsetmodified(z,cols,sz) +%------------------------------------------- +%Calculate offset required to plot coordinates in viewing mode specified by +%type. +%This is a copy of spect.spectperfusionsegmentation('calcoffset') in order +%to avoid using spect package + +c = 1+mod(z-1,cols); +r = ceil(z/cols); +yofs = (c-1)*sz(2); +xofs = (r-1)*sz(1); + +%------------------------------- +function z = remapuint8modified(im,cmap) %#ok +%------------------------------- +%Remap from image data to true color using color lookup. +%Function modified from calcufunctions.m to not be dependent on NO +%This is a copy of spect.spectperfusionsegmentation('remapuint8') in order +%to avoid using spect package + +warning off all; +cmap = uint8(255*cmap); +cmax = length(cmap); +cmin = 1; + +sz = size(im); +if isa(im,'single')||isa(im,'double') + z = max(min(round(cmax*im(:)),cmax),cmin); +elseif isa(im,'int16') + mi = min(im(:)); + ma = max(im(:)); + im = single(im(:)); + z = uint8(floor((im-mi)/(ma-mi)*256)); + z = uint8(z)+1; +else + myfailed(dprintf('Segment does not (yet) support type:%s',class(im))); +end + +if (size(cmap,2)==3) + % Extract r,g,b components + z3 = repmat(uint8(0),[size(z) 3]); + z3(:,1) = cmap(z,1); + z3(:,2) = cmap(z,2); + z3(:,3) = cmap(z,3); + z = reshape(z3,[sz 3]); +else + %Index color + z3 = repmat(uint8(0),size(z)); + z3(:) = cmap(z(:),1); + z = reshape(z3,sz); +end + +%---------------- +function colorname = rgb2colorshortname(rgbtripple) %#ok +%---------------- +% function to get Matlab color short name from RGB tripplet +num = bin2dec(num2str(rgbtripple)); +switch num + case 5 + colorname = 'm'; % magenta + case 3 + colorname = 'c'; % cyan + case 2 + colorname = 'g'; % green + case 4 + colorname = 'r'; % red + case 0 + colorname = 'k'; % black + case 7 + colorname = 'w'; % white + case 1 + colorname = 'b'; % blue + otherwise + colorname = 'y'; +end + +%---------------- +function [interpX, interpY] = resetinterpolationpoints(type) %#ok +%---------------- +% this function recalculates new coordinates for existing interpolation +% points based on their distance to the new contour +global SET NO +no = NO; +interpX = SET(no).([type,'InterpX']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice}; +interpY = SET(no).([type,'InterpY']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice}; + +contourX = SET(no).([type,'X']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice}; +contourY = SET(no).([type,'Y']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice}; + +for point = 1:length(interpX) + % calc distance + distx = min(contourX-interpX(point)); + disty = min(contourY-interpY(point)); + interpX(point) = interpX(point)-distx; +end + +%---------------- +function updatemarandscar(no) %#ok +%---------------- +% this function recalculates MaR and Scar if those exist +global SET +if not(isempty(SET(no).Scar)) + %update scar calculation + viability('viabilitycalc'); +end +if not(isempty(SET(no).MaR)) % redo MaR segmentation since LV was changed + if not(isempty(SET(no).MaR.MR.Artery)) + t2wmarsegmentation('domarsegmentation_Callback'); + else + mymsgbox('Set culprit artery and redo the automatic MaR') + mar('auto_Callback'); + end +end + +%---------------- +function d = calcdistpointoline(pt,xpoints,ypoints) %#ok +%---------------- +% this function calculates distance from clicked point to a line give by +% two points v1 and v2 +v1 = [xpoints(1) ypoints(1) 0]; +v2 = [xpoints(2) ypoints(2) 0]; +a = v1 - v2; +b = pt - v2; +d = norm(cross(a,b)) / norm(a); + + +%---------------- +function [xpoints,ypoints] = calcpointsoutsideLV(xpoints,ypoints,no) %#ok +%---------------- +% this function replaces RV endo points that lie inside LV with points that +% are outside LV +global SET +% get current LV Epi data +curtf = SET(no).CurrentTimeFrame; +curslice = SET(no).CurrentSlice; +if ~isempty(SET(no).EpiX) && ~isempty(SET(no).EpiY) + epix = SET(no).EpiX(:,curtf,curslice); + epiy = SET(no).EpiY(:,curtf,curslice); + if not(any(isnan(epix)) || any(isnan(epiy))) + % Here we slightly expand LV Epi contour used for calculation of + % the new point location so that RV Endo points are not exactly on + % the Epi contour but slightly outside (code borrowed from + % expand/contract function) + %f = 1.03; + f=1; %RV should lie on EPI-LV in septal part + sz = size(SET(no).EpiX,1); + mx = repmat(mean(epix),sz,1); + my = repmat(mean(epiy),sz,1); + epix = mx+f*(epix-mx); + epiy = my+f*(epiy-my); + % get cursor points inside and on LV epi + [inlvepi, onlvepi] = inpolygon(xpoints,ypoints,epix,epiy); + inlvepi = inlvepi + onlvepi; + if any(inlvepi) + % if there points inside, the replace them with LV Epi points with the + % shortest distance + for curpoint = 1:length(inlvepi) % go over all points + if inlvepi(curpoint) + % get index of the point that is closest to RV Endo in expanded + % Epi and replace the coordinates with this point + [~, ind] = findfunctions('dist2contour','Epi',no,xpoints(curpoint),ypoints(curpoint),curslice,curtf); + xpoints(curpoint) = epix(ind); + ypoints(curpoint) = epiy(ind); + end + end + end + end +end + +%---------------- +function imP = imtopolar(imR, rMin, rMax, M, N) %#ok +%---------------- +%IMTOPOLAR converts rectangular image to polar form. The output image is +% an MxN image with M points along the r axis and N points along the theta +% axis. The origin of the image is assumed to be at the center of the given +% image. The image is assumed to be grayscale. +% Bilinear interpolation is used to interpolate between points not exactly +% in the image. +% +% rMin and rMax should be between 0 and 1 and rMin < rMax. r = 0 is the +% center of the image and r = 1 is half the width or height of the image. +% +% V0.1 7 Dec 2007 (Created), Prakash Manandhar pmanandhar@umassd.edu + +[Mr, Nr] = size(imR); % size of rectangular image +Om = (Mr+1)/2; % co-ordinates of the center of the image +On = (Nr+1)/2; +sx = (Mr-1)/2; % scale factors +sy = (Nr-1)/2; + +imP = zeros(M,N); + +delR = (rMax - rMin)/(M-1); +delT = 2*pi/N; + +for ri = 1:M + for ti = 1:N + r = rMin + (ri - 1)*delR; + t = (ti - 1)*delT; + x = r*cos(t); + y = r*sin(t); + xR = x*sx + Om; + yR = y*sy + On; + imP(ri, ti) = interpolate(imR, xR, yR); + end +end + +%---------------- +function v = interpolate(imR, xR, yR) +%---------------- +%INTERPOLATE used in IMTOPOLAR +% +% V0.1 7 Dec 2007 (Created), Prakash Manandhar pmanandhar@umassd.edu + +xf = floor(xR); +xc = ceil(xR); +yf = floor(yR); +yc = ceil(yR); +if xf == xc && yc == yf + v = imR(xc,yc); +elseif xf == xc + v = imR(xf,yf) + (yR - yf)*(imR(xf,yc) - imR(xf,yf)); +elseif yf == yc + v = imR(xf,yf) + (xR - xf)*(imR(xc,yf) - imR(xf,yf)); +else + A = [ xf yf xf*yf 1 + xf yc xf*yc 1 + xc yf xc*yf 1 + xc yc xc*yc 1 ]; + r = [ imR(xf, yf) + imR(xf,yc) + imR(xc,yf) + imR(xc,yc) ]; + a = A\double(r); + w = [xR yR xR*yR 1]; + v = w*a; +end \ No newline at end of file diff --git a/source/callbackfunctions.m b/source/callbackfunctions.m new file mode 100644 index 0000000..aba5807 --- /dev/null +++ b/source/callbackfunctions.m @@ -0,0 +1,1869 @@ +function callbackfunctions(varargin) +% This .m file has the ambition of containing all Callback functions + +% Split out by Klas + +%Invoke subfunction +macro_helper(varargin{:}); %future macro recording use +feval(varargin{:}); % FEVAL switchyard + +%--------------------- +function orthoview_Callback %#ok +%----------------------- +global SET NO +%First we check so that there are any slices because if not there is no +%point + +if SET(NO).ZSize==1 + myfailed('To few slices for orthogonal view.') + return +end + +%this sets all necessary fields +viewfunctions('orthoview',NO); + +%This updates the view. +viewfunctions('setview',2,2,ones(1,4)*NO,{'orth','hla','vla','gla'}) + +%------------------------------ +function viewviewport_Callback %#ok +%------------------------------ +%Displays viewport in one panel + +global DATA + +segment3dp.tools('storetoobject'); + +viewfunctions('setview',1,1,[],{'speedim'}) + +DATA.drawlist = []; +DATA.drawlist{1} = {'segment3dp.tools(''helprender'');'}; + +drawfunctions('setxynan',1); + +run = true; +DATA.Handles.configiconholder.indent('view3d',run); + +segment3dp.tools('helprender'); + +DATA.LevelSet.ViewPort.panelhandle.Position = DATA.Handles.imageaxes(1).Position; + +%------------------------------ +function view4panel3dp_Callback %#ok +%------------------------------ +global DATA + +%indent(DATA.Handles.configiconholder,'view4',1); + +segment3dp.tools('storetoobject'); + +viewfunctions('setview',2,2,[],{'trans3DP','speedim','sag3DP','cor3DP'}) + +if DATA.Handles.configiconholder.findindented('view3d') + %Update the size + DATA.LevelSet.ViewPort.panelhandle.Position = DATA.Handles.imageaxes(2).Position; + DATA.drawlist{2} = {'segment3dp.tools(''helprender'');'}; +end + +%---------------------------- +function selectpanel_Callback(name) %#ok +%---------------------------- +%Select the panel with name + +global DATA SET + +selpanel = []; +for loop = 1:length(DATA.ViewPanelsType) + if isequal(DATA.ViewPanelsType{loop},name) + selpanel = loop; + end +end + +%if ~isempty(selpanel) +% segment('switchtopanel',selpanel) +%end + +if ~isempty(selpanel) + DATA.CurrentPanel = selpanel; + no = DATA.ViewPanels(selpanel); + switch name + case 'trans3DP' + SET(no).LevelSet.Pen.Color = 'r'; + case 'sag3DP' + SET(no).LevelSet.Pen.Color = 'g'; + case 'cor3DP' + SET(no).LevelSet.Pen.Color = 'b'; + end + + for loop = 1:length(DATA.ViewPanelsType) + if isequal(DATA.ViewPanelsType{loop},name) + DATA.CurrentPanel = loop; + end + end + + %Graphical update + drawfunctions('drawselectedframe',selpanel) + speedimpanel = find(strcmp(DATA.ViewPanelsType,'speedim')); + if isempty(speedimpanel) + return + end + drawfunctions('drawpanel',speedimpanel); + viewfunctions('updatezoomandaspectratio',speedimpanel); +end + +%------------------------ +function viewhelper(type) +%------------------------ +%Set a two panel view with anatomical and speed image +global DATA SET NO + +segment3dp.tools('storetoobject'); + +speedpanel = 2; %currently is always panel number2 + +switch type + case 'trans3DP' + SET(NO).LevelSet.Pen.Color = 'r'; + case 'sag3DP' + SET(NO).LevelSet.Pen.Color = 'g'; + case 'cor3DP' + SET(NO).LevelSet.Pen.Color = 'b'; +end + +if DATA.Handles.configiconholder.findindented('view3d') + + %Clear all graphics function from drawlist + drawfunctions('setxynan',2) + viewfunctions('setview',1,2,[],{type,'viewport'}) + + %Update the size + DATA.LevelSet.ViewPort.panelhandle.Position = DATA.Handles.imageaxes(2).Position; + + DATA.drawlist{speedpanel} = {'segment3dp.tools(''helprender'');'}; + +else + viewfunctions('setview',1,2,[],{type,'speedim'}) + %viewfunctions('updatezoomandaspectratio',1); + %viewfunctions('updatezoomandaspectratio',2); +end + +%---------------------------- +function viewtransversal_Callback %#ok +%---------------------------- +viewhelper('trans3DP'); + +%---------------------------- +function viewcoronal_Callback %#ok +%---------------------------- +viewhelper('cor3DP'); + +%---------------------------- +function viewsagittal_Callback %#ok +%---------------------------- +viewhelper('sag3DP'); + +%---------------------------- +function reset3d_Callback %#ok +%---------------------------- +%Reset 3D view + +global DATA + +if segment3dp.isviewportalive + %3D display on rotate + volshowobject = DATA.LevelSet.ViewPort.getvolshowobject; + + %Reset to + newpos = [0 -4 0]; + + %Set the new camera position + ax = DATA.LevelSet.ViewPort.getaxeshandle; + volshowobject.CameraPosition = newpos; + volshowobject.CameraUpVector = [0 0 -1]; + ax.CameraPosition = newpos; + ax.CameraUpVector = [0 0 -1]; +end + +%------------------------------------------ +function set3dvieworientation_Callback(view) %#ok +%------------------------------------------ +%Set predefined views + +global DATA + +newposition = []; +newvector = []; + +%Check if viewport is active +if segment3dp.isviewportalive + + d = 4; + + switch view + case 'transversal' + newposition = [0 0 -d]; + newvector = [0 -1 0]; + case 'sagittal' + newposition = [-d 0 0]; + newvector = [0 0 -1]; + case 'coronal' + newposition = [0 -d 0]; + newvector = [0 0 -1]; + end + + %Make the update + if ~isempty(newposition) + DATA.LevelSet.ViewPort.setcameraposition(newposition); + end + + if ~isempty(newvector) + DATA.LevelSet.ViewPort.setcameraupvector(newvector); + end + + DATA.LevelSet.ViewPort.updatepoints; +end + +%----------------------------------- +function set3dviewotherside_Callback %#ok +%----------------------------------- +%Set predefined views + +global DATA + +%Check if viewport is active +if segment3dp.isviewportalive + p = DATA.LevelSet.ViewPort.getcameraposition; + DATA.LevelSet.ViewPort.setcameraposition(-p); + DATA.LevelSet.ViewPort.updatepoints; +end + +%---------------------------- +function zoomin3d_Callback(f) %#ok +%---------------------------- +%Zoom in viewpanel + +global DATA + +if segment3dp.isviewportalive + pos = DATA.LevelSet.ViewPort.getvolshowobject.CameraPosition; + DATA.LevelSet.ViewPort.setcameraposition(pos*(1+f)); + DATA.LevelSet.ViewPort.updatepoints; +end + +%-------------------------------------- +function rotate3d_Callback(dtheta,dphi) %#ok +%-------------------------------------- +%Rotate 3D view with dtheta, and dphi degrees +%Obs this function is not defined from RLAPFH coordinate system + +global DATA + +if segment3dp.isviewportalive + + %3D display on rotate + volshowobject = DATA.LevelSet.ViewPort.getvolshowobject; + pos = volshowobject.CameraPosition; + + r = sqrt(sum(pos.*pos)); + theta = acos(pos(3)/r); + phi = atan2(pos(2),pos(1)); + + theta = theta+dtheta/180*pi; + phi = phi+dphi/180*pi; + + newpos = [... + r*sin(theta)*cos(phi) ... + r*sin(theta)*sin(phi) ... + r*cos(theta)]; + + %Set the new camera position + ax = DATA.LevelSet.ViewPort.getaxeshandle; + volshowobject.CameraPosition = newpos; + ax.CameraPosition = newpos; + +end + +%---------------------- +function lasso_Callback %#ok +%---------------------- +%Lasso placeholder + +myfailed('Lasso not yet available.'); + +%--------------------- +function mmode_Callback %#ok +%----------------------- +myfailed('This functions is no longer available.') + +%--------------------- +function play_Callback(panels) %#ok +%----------------------- +global DATA SET + +if nargin == 0 + panels = find(DATA.ViewPanels>0); +end + +maxt = 0; +for loop=DATA.ViewPanels(panels) + if SET(loop).TSize>maxt + maxt = SET(loop).TSize; + end +end + +if maxt == 1 + myfailed('Need a time resolved image stack') + undent(DATA.Handles.permanenticonholder,'play',0) + return +end + +%Try different approach where all stacks are played after NO +startframes = SET(DATA.ViewPanels(panels(1))).CurrentTimeFrame; +starttime = now; +beattime = SET(DATA.ViewPanels(panels(1))).BeatTime; + +%prior to running the following graphics objects are turned 'off' by +%setting xdata and ydata to nan. This is because these objects need to be +%many in order to e.g draw text at multiple locations. +for p = panels + % % % for c = 'cygmkwrb' + % % % set(DATA.Handles.([c,'roitext'])(p,:),'Position',[nan,nan]) + % % % end + set(DATA.Handles.roitext(p,:),'Position',[nan,nan]) + set(DATA.Handles.measurementtext(p,:),'Position',[nan,nan]) + set(DATA.Handles.pointtext(p,:),'Position',[nan,nan]) + + %interps not necessary when playing + type = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; + for t = 1:length(type) + DATA.Handles.(lower(type{t}))(p).XData = nan; + DATA.Handles.(lower(type{t}))(p).YData = nan; + end +end + +synchronize = findindented(DATA.Handles.hideiconholder,'synchronize'); + +DATA.Run=1; +t = maxt; +while DATA.Run%true + %stopping criteria + if ~findindented(DATA.Handles.permanenticonholder,'play') + DATA.Run=0; + end + + for p = panels + no = DATA.ViewPanels(p); + if SET(no).TSize>1 + if DATA.Record + t = 1+mod(t,maxt); + else + t = 1+mod(floor(rem(now-starttime,1)*24*3600/(beattime/maxt)+startframes),maxt); + end + SET(DATA.ViewPanels(p)).CurrentTimeFrame = max(min(round(SET(no).TSize*(t/maxt)),SET(no).TSize),1); + drawfunctions('drawpanel',p); + end + end + + %also update the timebars! + viewfunctions('updatetimebars',synchronize) + drawnow %limitrate + if DATA.Record %For Automatic Record Movie functionality + %drawnow; + gui = DATA.GUI.Segment; + DATA.MovieFrame = mygetframe(gui.fig); + DATA.MovieFrame.colormap=colormap(gui.fig); + %DATA.MovieFrame = mygetframe(gui.handles.imageaxes); + export('exportmovierecorder_Callback','newframe'); + end +end + +%--------------------- +function play_Callback2(panels) %#ok +%----------------------- +global DATA SET NO + +if nargin == 0 + %panels = 1:length(DATA.ViewPanels); + panels = find(DATA.ViewPanels>0);%1:length(DATA.ViewPanels); +end + +maxt = 0; +for loop=DATA.ViewPanels(panels) + if SET(loop).TSize>maxt + maxt = SET(loop).TSize; + end +end + +if maxt == 1 + myfailed('Need a time resolved image stack') + undent(DATA.Handles.permanenticonholder,'play',0) + return +end + +%Try different approach where all stacks are played after NO +%startframes = SET(DATA.ViewPanels(panels(1))).CurrentTimeFrame; +%starttime = now; +%beattime = SET(DATA.ViewPanels(panels(1))).BeatTime; + +%prior to running the following graphics objects are turned 'off' by +%setting xdata and ydata to nan. This is because these objects need to be +%many in order to e.g draw text at multiple locations. +for p = panels + set(DATA.Handles.roitext(p,:),'Position',[nan,nan]) + set(DATA.Handles.measurementtext(p,:),'Position',[nan,nan]) + set(DATA.Handles.pointtext(p,:),'Position',[nan,nan]) + set(DATA.Handles.pointtext(p),'Position',[nan,nan]) + + %interps not necessary when playing + type = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; + for t = 1:length(type) + DATA.Handles.(lower(type{t}))(p).XData = nan; + DATA.Handles.(lower(type{t}))(p).YData = nan; + end +end + +DATA.Run=1; +while DATA.Run%true + %stopping criteria + tic + if ~findindented(DATA.Handles.permanenticonholder,'play') + DATA.Run=0; + end + + %Update current timeframe in NO + if SET(NO).CurrentTimeFrame < SET(NO).TSize + SET(NO).CurrentTimeFrame = SET(NO).CurrentTimeFrame+1; + else + SET(NO).CurrentTimeFrame = 1; + end + + for p = panels + no = DATA.ViewPanels(p); + if SET(no).TSize>1 + %t = 1+mod(floor(rem(now-starttime,1)*24*3600/(beattime/maxt)+startframes),maxt); + %SET(DATA.ViewPanels(p)).CurrentTimeFrame = max(min(round(SET(no).TSize*(t/maxt)),SET(no).TSize),1); + + %find the closest matching phase to the currenttimeframe in NO + [~,t]= min((SET(NO).TimeVector(SET(NO).CurrentTimeFrame)/SET(NO).TimeVector(end)-SET(no).TimeVector/SET(no).TimeVector(end)).^2); + + %if t~=SET(no).CurrentTimeFrame || no ~=NO + SET(no).CurrentTimeFrame = t; + drawfunctions('drawpanel',p); + %end + end + end + + %also update the timebars! + viewfunctions('updatetimebars') + drawnow + + %then we get the spent time rendering and pause for the residual + t_time = toc; + if t_time +%------------------------------------------- +%Clear all LV segmentation, both endo and epi + +global DATA + +if nargin==1 + if ~yesno('Do you really want to remove all LV segmentation ?',[],DATA.GUI.Segment) + % myfailed('Aborted by user.',DATA.GUI.Segment); + return; + end +end + +segmentation('clearalllv_Callback'); + +%------------------------------------------- +function segmentclearallrv_Callback %#ok +%------------------------------------------- +%Clear all RV segmentation, both endo and epi + +global DATA + +if nargin==1 + if ~yesno('Do you really want to remove all RV segmentation ?',[],DATA.GUI.Segment) + % myfailed('Aborted by user.',DATA.GUI.Segment); + return; + end +end + +segmentation('clearallrv_Callback'); + +%------------------------------------------------------- +function segmentclearalllvbutsystolediastole_Callback %#ok +%------------------------------------------------------- +%Clears all LV segmentation except in systole and diastole. + +global SET NO DATA + +if SET(NO).TSize<2 + myfailed('Not timeresolved data, aborting.',DATA.GUI.Segment); + return; +end + +if isequal(SET(NO).EDT,SET(NO).EST) + myfailed('Systole and diastole occurs at the same time frame, aborting.',DATA.GUI.Segment); + return; +end + +%Create index structure +ind = true(1,SET(NO).TSize); +ind(SET(NO).EDT) = false; +ind(SET(NO).EST) = false; +arg = struct('endo',true,'epi',true,'rvendo',false,'rvepi',false); +indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); +segmentation('removeallinterp_Callback',true,[],arg,indarg); + +%Create index structure +ind = true(1,SET(NO).TSize); +ind(SET(NO).EDT) = false; +ind(SET(NO).EST) = false; + +if ~isempty(SET(NO).EndoX) + SET(NO).EndoX(:,ind,:) = NaN; + SET(NO).EndoY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).EpiX) + SET(NO).EpiX(:,ind,:) = NaN; + SET(NO).EpiY(:,ind,:) = NaN; +end + +SET(NO).EndoDraged(ind,:) = false; +SET(NO).EpiDraged(ind,:) = false; + +lvsegchanged = true; segment('updatevolume',lvsegchanged); +drawfunctions('drawcontours', DATA.CurrentPanel) +drawfunctions('drawinterp', DATA.CurrentPanel) + + +%------------------------------------------------------- +function segmentclearallrvbutsystolediastole_Callback %#ok +%------------------------------------------------------- +%Clears all RV segmentation except in systole and diastole. + +global SET NO DATA + +if SET(NO).TSize<2 + myfailed('Not timeresolved data, aborting.',DATA.GUI.Segment); + return; +end + +if isequal(SET(NO).EDT,SET(NO).EST) + myfailed('Systole and diastole occurs at the same time frame, aborting.',DATA.GUI.Segment); + return; +end + +%Create index structure +ind = true(1,SET(NO).TSize); +ind(SET(NO).EDT) = false; +ind(SET(NO).EST) = false; +arg = struct('endo',false,'epi',false,'rvendo',true,'rvepi',true); +indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); +segmentation('removeallinterp_Callback',true,[],arg,indarg); + +if ~isempty(SET(NO).RVEndoX) + SET(NO).RVEndoX(:,ind,:) = NaN; + SET(NO).RVEndoY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).RVEpiX) + SET(NO).RVEpiX(:,ind,:) = NaN; + SET(NO).RVEpiY(:,ind,:) = NaN; +end + +SET(NO).EndoDraged(ind,:) = false; +SET(NO).EpiDraged(ind,:) = false; + +segment('updatevolume'); +drawfunctions('drawcontours',DATA.CurrentPanel) +drawfunctions('drawinterp',DATA.CurrentPanel) + +%----------------------------------------- +function contextloadno_Callback(viewpanelstype) %#ok +%----------------------------------------- +%Loads imagestack no with the desired viewmode +global DATA + +no = DATA.LastObject; +%Already out then switch to it and change viewmode +if any(no==DATA.ViewPanels) + viewfunctions('switchimagestack',no,viewpanelstype) +else %add to first + viewfunctions('addno2panel',1,no,viewpanelstype) +end + +DATA.LastObject = []; + + +%----------------------------------------- +function pointdeletethis_Callback %#ok +%----------------------------------------- +%remove point closest to click +global DATA SET +no = DATA.ViewPanels(DATA.CurrentPanel); +pointind = DATA.LastObject(1); +slice = DATA.LastObject(2); +tf = DATA.LastObject(3); + +SET(no).Point.X(pointind) = []; +SET(no).Point.Y(pointind) = []; +SET(no).Point.T(pointind) = []; +SET(no).Point.Z(pointind) = []; +SET(no).Point.Label(pointind) = []; + +drawfunctions('drawno',no); + +%----------------------------------------- +function pointrenamethis_Callback %#ok +%----------------------------------------- +%rename point closest to click +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if noobjectshelper + return +end + +pointind = DATA.LastObject(1); +if strcmp(DATA.ProgramName, 'Segment 3DPrint') + s = myinputdlg({'Enter name'},'Name',1,{sprintf('%s',SET(no).Point.Label{pointind})}); + if isempty(s) || isempty(s{1}) + return; + else + SET(no).Point.Label{pointind} = s{1}; + end +else + % in other programs show a pre-defined set of names + menuitems = {... + 'Apex',... + 'RV insertion',... + 'RV insertion Anterior',... + 'RV insertion Inferior',... + 'AV plane',... + 'TV plane',... + 'P1',... + 'P2',... + 'General',... + 'Sector start',... + 'User defined ...'}; + + % s = myinputdlg({'Enter name'},'Name',1,{sprintf('%s',SET(no).Point.Label{pointind})}); + + s = mymenu(strcat(dprintf('Select a new name for the point')),menuitems,DATA.GUI.Segment); + if isempty(s) + myfailed('Invalid name.',DATA.GUI.Segment); + return; + elseif s == 0 % cancel was clicked + return + elseif s == length(menuitems) + % user defined name + name = myinputdlg({'Enter name'},'Name',1,{sprintf('%s',SET(no).Point.Label{pointind})}); + if isempty(name) || isempty(name{1}) + return; + else + SET(no).Point.Label{pointind} = name{1}; + end + else + SET(no).Point.Label{pointind} = menuitems{s}; + end +end + +drawfunctions('drawno',no); + +%----------------------------------------- +function pointclearall_Callback %#ok +%----------------------------------------- +%remove all points + +global DATA SET NO + +no = NO;%DATA.ViewPanels(DATA.CurrentPanel); + +SET(no).Point.X = []; +SET(no).Point.Y = []; +SET(no).Point.T = []; +SET(no).Point.Z = []; +SET(no).Point.Label = {}; + +drawfunctions('drawno',no); +if any(strcmp(DATA.ProgramName,{'Segment 3DPrint'})) + if segment3dp.isviewportalive + DATA.LevelSet.ViewPort.setpoints(NaN,NaN,NaN) + end +end + +%----------------------------------------- +function pointmaketimeresolvedthis_Callback %#ok +%----------------------------------------- +%make point closest to click timeresolved +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if noobjectshelper + return +end + +pointind = DATA.LastObject(1); + +%nan means timeresolved. +SET(no).Point.T(pointind) = nan; + +drawfunctions('drawno',no); + +%----------------------------------------- +function pointshowthisframeonly_Callback %#ok +%----------------------------------------- +%remove point closest to click +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if noobjectshelper + return +end + +pointind = DATA.LastObject(1); +tf = DATA.LastObject(3); + +SET(no).Point.T(pointind) = tf; + +drawfunctions('drawno',no); + +%----------------------------------------- +function interpdeletepoint %#ok +%----------------------------------------- +%remove interpolation point closest to click + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if noobjectshelper + return +end + +pointind = DATA.LastObject(1); +slice = DATA.LastObject(2); +tf = DATA.LastObject(3); +pointtype = DATA.LastObjectType; + +SET(no).([pointtype,'X']){tf,slice}(pointind) = []; +SET(no).([pointtype,'Y']){tf,slice}(pointind) = []; + +%do resampling of curve when deleting single point. +X = SET(no).([pointtype,'X']){tf,slice}; +Y = SET(no).([pointtype,'Y']){tf,slice}; +%removes duplicate points and resamples the contour +[x,y] = calcfunctions('resamplecurve',X,Y,DATA.NumPoints-1); +SET(no).([pointtype(1:end-6),'Y'])(:,tf,slice)=[y,y(1)]; +SET(no).([pointtype(1:end-6),'X'])(:,tf,slice)=[x,x(1)]; + +drawfunctions('drawno',no); + +%----------------------------------------- +function interpdeletepointthisslicephase %#ok +%----------------------------------------- +%remove interpolation point closest to click +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if noobjectshelper + return +end + +pointind = DATA.LastObject(1); +slice = DATA.LastObject(2); +tf = DATA.LastObject(3); +pointtype = DATA.LastObjectType; + +SET(no).([pointtype,'X']){tf,slice} = []; +SET(no).([pointtype,'Y']){tf,slice} = []; + +drawfunctions('drawno',no); + +%------------------------------------- +function measureclearthis_Callback(~) %#ok +%------------------------------------- +%Clear this measurement + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if nargin==0 + if noobjectshelper + return + end + measureind = DATA.LastObject(1); +else + %Ask + measureind = measureaskhelper; +end + +if isequal(measureind,0) + % myfailed('Aborted.'); + return; +end + +SET(no).Measure(measureind) = []; +drawfunctions('drawno',no); +segment('updatemeasurement'); + +%-------------------------------- +function measureclearall_Callback %#ok +%-------------------------------- +%Clear all measurements + +global DATA SET +no = DATA.ViewPanels(DATA.CurrentPanel); + +SET(no).Measure = []; +drawfunctions('drawno',no); +segment('updatemeasurement'); + +%---------------------------- +function m = measureaskhelper +%---------------------------- +%Helper function to select a measurement in a menu + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +m = 0; +if isempty(SET(no).Measure) + myfailed('No measurements.'); + return; +end + +if length(SET(no).Measure)==1 + m = 1; + return; +end + +%Loop over names +namecell = cell(1,length(SET(no).Measure)); +for loop = 1:length(namecell) + namecell{loop} = SET(no).Measure(loop).LongName; + if isempty(namecell{loop}) + namecell{loop} = 'Empty name'; + end +end + +%ask +m = mymenu('Select measurement',namecell); + +%------------------------------------- +function measurerenamethis_Callback(~) %#ok +%------------------------------------- +%Rename measurement + +global DATA SET + +no = DATA.ViewPanels(DATA.CurrentPanel); + +if nargin==0 + if noobjectshelper + return + end + measureind = DATA.LastObject(1); +else + %ask + measureind = measureaskhelper; +end + +if isequal(measureind,0) + % myfailed('Aborted.'); + return; +end + +tools('enableundo',no); + +%Get new name +[stri,lstr] = measureasklabel(measureind); +if ~isempty(stri) + SET(no).Measure(measureind).Name = stri; + SET(no).Measure(measureind).LongName = lstr; +else + myfailed('Invalid name.',DATA.GUI.Segment); + return; +end + +drawfunctions('drawno',no) +segment('updatemeasurement'); + +%---------------------------------- +function doreturn = noobjectshelper +%---------------------------------- +%Helper function that checks for LastObject + +global DATA + +if isempty(DATA.LastObject) + myfailed('No objects'); + doreturn = true; +else + doreturn = false; +end + +%------------------------------ +function [stri,lstr] = measureasklabel(measureind) +%------------------------------ +%Asks for a label of a measurement. + +global DATA + +%Call overloaded method +[stri,lstr] = DATA.measureasklabel(measureind); + +segment('updatemeasurement'); + + +%--------------------------------------- +function interpdeletepointall(pointtype) +%--------------------------------------- +%remove interpolation point closest to click +global DATA SET +no = DATA.ViewPanels(DATA.CurrentPanel); +if nargin < 1 + pointtype = DATA.LastObjectType; +end + +SET(no).([pointtype,'X']) = []; +SET(no).([pointtype,'Y']) = []; + +drawfunctions('drawno',no); + +%----------------------------------------- +function clearallslices_Callback %#ok +%----------------------------------------- +%Clear all segmentation, both endo and epi, lv and rv mar and scar. + +segmentation('clearslices_Callback'); + +%----------------------------------------- +function segmentclearall_Callback(silent) %#ok +%----------------------------------------- +%Clear all segmentation, both endo and epi, lv and rv mar and scar. + +global DATA + +if nargin == 0 || not(silent) + msg = dprintf('This removes all existing segmentation of LV, RV, ROI, MaR and scar. Are you sure?'); + if ~yesno(msg,[],DATA.GUI.Segment) + return; + end +end + +viability('viabilityclear_Callback'); +roi('roiclearall_Callback') +segmentation('clearall_Callback'); +mar('clearall_Callback'); + + +%----------------------------------------------------- +function segmentclearallbutsystolediastole_Callback +%----------------------------------------------------- +%Clears all segmentation in all timeframes but systole and diastole. +global DATA SET NO + +if SET(NO).TSize<2 + myfailed('Not timeresolved data, aborting.',DATA.GUI.Segment); + return; +end + +if isequal(SET(NO).EDT,SET(NO).EST) + myfailed('Systole and diastole occurs at the same time frame, aborting.',DATA.GUI.Segment); + return; +end + +%Create index structure +ind = true(1,SET(NO).TSize); +ind(SET(NO).EDT) = false; +ind(SET(NO).EST) = false; +arg = struct('endo',true,'epi',true,'rvendo',true,'rvepi',true); +indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); +segmentation('removeallinterp_Callback',true,[],arg,indarg); + +if ~isempty(SET(NO).EndoX) + SET(NO).EndoX(:,ind,:) = NaN; + SET(NO).EndoY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).EpiX) + SET(NO).EpiX(:,ind,:) = NaN; + SET(NO).EpiY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).RVEndoX) + SET(NO).RVEndoX(:,ind,:) = NaN; + SET(NO).RVEndoY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).RVEpiX) + SET(NO).RVEpiX(:,ind,:) = NaN; + SET(NO).RVEpiY(:,ind,:) = NaN; +end + +SET(NO).EndoDraged(ind,:) = false; +SET(NO).EpiDraged(ind,:) = false; + +segment('updatevolume'); +drawfunctions('drawcontours',DATA.CurrentPanel); +drawfunctions('drawinterp',DATA.CurrentPanel); + +%-------------------------------------------- +function segmentclearallbutdiastole_Callback +%-------------------------------------------- +%Clears all segmentation in all timeframes but diastole. +global DATA SET NO + +if SET(NO).TSize<2 + myfailed('Not timeresolved data, aborting.',DATA.GUI.Segment); + return; +end + +%Create index structure +ind = true(1,SET(NO).TSize); +ind(SET(NO).EDT) = false; +arg = struct('endo',true,'epi',true,'rvendo',true,'rvepi',true); +indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); +segmentation('removeallinterp_Callback',true,[],arg,indarg); + +if ~isempty(SET(NO).EndoX) + SET(NO).EndoX(:,ind,:) = NaN; + SET(NO).EndoY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).EpiX) + SET(NO).EpiX(:,ind,:) = NaN; + SET(NO).EpiY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).RVEndoX) + SET(NO).RVEndoX(:,ind,:) = NaN; + SET(NO).RVEndoY(:,ind,:) = NaN; +end + +if ~isempty(SET(NO).RVEpiX) + SET(NO).RVEpiX(:,ind,:) = NaN; + SET(NO).RVEpiY(:,ind,:) = NaN; +end + +SET(NO).EndoDraged(ind,:) = false; +SET(NO).EpiDraged(ind,:) = false; + +segment('updatevolume'); +drawfunctions('drawcontours',DATA.CurrentPanel); +drawfunctions('drawinterp',DATA.CurrentPanel); + + +%------------------------------------ +function result = updateintersections_Callback(slices,no,type) %#ok +%------------------------------------ +% Calculates the intersection of a endocardial segmentation +% and SET(no) for +% slices == 'all' +% or +% slices == 'current' +% +% Allowed segmenation 'type' is 'LVEndo' or 'RVEndo' +% +% Calculates intersection for SET(NO) if nargin==1. +% Returns false if calculations fails + +% Marten Larsson, June, 2009 + +global DATA NO SET + +if nargin == 1 + no = NO; + type = 'LV Endocardial'; +end + +result = true; +segno = []; + +switch type + case 'LV Endocardial' + % Find sets with LV endocardial segmentation + for i=1:length(SET) + if ~isempty(SET(i).EndoX) && any(any(any(~isnan(SET(i).EndoX)))) + segno = [segno i]; %#ok + end + end + case 'RV Endocardial' + % Find sets with RV endocardial segmentation + for i=1:length(SET) + if ~isempty(SET(i).RVEndoX) && any(any(any(~isnan(SET(i).RVEndoX)))) + segno = [segno i]; %#ok + end + end +end + +if isempty(segno) + myfailed('No segmentation found',DATA.GUI.Segment); + result = false; + return; +end + +if length(segno)>1 + segstring = cell(length(segno),1); + for i = 1: length(segno) + segstring{i} = dprintf('Image stack %d - %s',segno(i),SET(segno(i)).ImageType); + end + + [selected, ok] = listdlg('ListString',segstring,... + 'SelectionMode','single',... + 'PromptString','Chose image stack to use:',... + 'ListSize',[300 100]); + + if ~ok + result = false; + return; + end + segno = segno(selected); +end + +calcsegintersect(segno,no,slices,type); +viewfunctions('setview'); %drawfunctions('drawall'); + + +%---------------------- +function selectlvmethod %#ok +%---------------------- +%callback from 3DPrint auto LV icon to select if apply CT or MR auto LV seg + +global SET NO + +no = NO; +ismr = strfind(SET(no).ImagingTechnique,'MR'); +isct = strfind(SET(no).ImagingTechnique,'CT'); + +if not(isempty(ismr)) && isempty(isct) + lvsegmentation; +elseif not(isempty(isct)) && isempty(ismr) + ct.ctlicensecheck('CTLVSegmentation'); +else + %user select if it is CT or MR or cancel + menuitems{1} = 'MR'; + menuitems{2} = 'CT'; + menuitems{3} = 'Other'; + answer = mymenu('Select imaging technique for the selected image stack.',menuitems); + if answer + if answer == 1 + lvsegmentation; + elseif answer == 2 + ct.ctlicensecheck('CTLVSegmentation'); + elseif answer == 3 + myfailed('No automatic LV segmentation method for other imaging techniques avaliable.'); + end + else + disp('LV segmentation canceled.'); + end +end + +%--------------------------------------------- +function calccalciummask_Callback +%--------------------------------------------- +global SET NO +sizesetstruct=size(SET); + +temp=[]; +tempCaSc=[]; + +temp=[]; +tempCaSc=[]; + +if sizesetstruct(1,2)==1 + m=1; +else + m=2; +end + +for n=1:sizesetstruct(1,m) + temp=[temp isempty(SET(n).EndoX)==0]; + tempCaSc=[tempCaSc contains(SET(n).SeriesDescription,'CaSc')]; +end +sumtempCaSc= sum(tempCaSc); +if sum(temp)==0 + myfailed('there is no contrastimage') + return +end +if sum(temp)==1 + seg= find(temp); +elseif sum(temp)==2 + findindex1=find(temp); + seg = mymenu('Choose segmentation stack',['Image stack no ' num2str(SET(findindex1(1)).Linked)], ['Image stack no ' num2str(SET(findindex1(2)).Linked)]); +end + +if sumtempCaSc==0 + myfailed('There is no Ca image') + return +end +if sumtempCaSc==1 + no=find(tempCaSc); +elseif sumtempCaSc==2 + findindex=find(tempCaSc); + no = mymenu('In which image stack do you want to detect calcium?',['Image stack no ' num2str(SET(findindex(1)).Linked)], ['Image stack no ' num2str(SET(findindex(2)).Linked)]); + no=findindex(no); +elseif sumtempCaSc==3 + no = mymenu('In which image stack do you want to detect calcium?',['Image stack no ' num2str(SET(findindex(1)).Linked)], ['Image stack no ' num2str(SET(findindex(2)).Linked)], ['Image stack no ' num2str(SET(findindex(3)).Linked)]); + no=findindex(no); +end + +callbackfunctions('calccalciummask',no,seg,0) + +%--------------------------------------------- +function splitcalciummask_Callback +%---------------------------------------------? + +global SET NO +sizesetstruct=size(SET); + +temp=[]; +tempCaSc=[]; + +if sizesetstruct(1,2)==1 + m=1; +else + m=2; +end + +for n=1:sizesetstruct(1,m) + temp=[temp isempty(SET(n).EndoX)==0]; + tempCaSc=[tempCaSc contains(SET(n).SeriesDescription,'CaSc')]; + %tempCaSc=[tempCaSc contains(SET(n).SeriesDescription,'CorASeq')]; +end +sumtempCaSc= sum(tempCaSc); +if sum(temp)==0 + % myfailed('There is no contrast image') + seg=0; +end +if sum(temp)==1 + seg= find(temp); +elseif sum(temp)>1 + %seg = mymenu('In which image stack do you want to use for the segmentation','e', 'e', 'Image stack no 3','Image stack no 4'); + myfailed('several contrastimages') + return +end + +if sumtempCaSc==0 + myfailed('There is no Ca image') + return +end +if sumtempCaSc==1 + no=find(tempCaSc); +elseif sumtempCaSc==2 + findindex=find(tempCaSc); + no = mymenu('In which image stack do you want to detect calcium?',['Image stack no ' num2str(SET(findindex(1)).Linked)], ['Image stack no ' num2str(SET(findindex(2)).Linked)]); + no=findindex(no); +elseif sumtempCaSc==3 + no = mymenu('In which image stack do you want to detect calcium?',['Image stack no ' num2str(SET(findindex(1)).Linked)], ['Image stack no ' num2str(SET(findindex(2)).Linked)],['Image stack no ' num2str(SET(findindex(3)).Linked)]); + no=findindex(no); + +end + + +callbackfunctions('calccalciummask',no,seg,1) + + +%--------------------------------------------- +function rawca_Callback +%---------------------------------------------? + +global SET NO +sizesetstruct=size(SET); + +temp=[]; +tempCaSc=[]; + +if sizesetstruct(1,2)==1 + m=1; +else + m=2; +end + +for n=1:sizesetstruct(1,m) + + tempCaSc=[tempCaSc contains(SET(n).SeriesDescription,'CaSc')]; + +end +sumtempCaSc= sum(tempCaSc); + +seg=0; + +if sumtempCaSc==0 + myfailed('There is no Ca image') + return +end +if sumtempCaSc==1 + no=find(tempCaSc); +elseif sumtempCaSc==2 + findindex=find(tempCaSc); + no = mymenu('In which image stack do you want to detect calcium?',['Image stack no ' num2str(SET(findindex(1)).Linked)], ['Image stack no ' num2str(SET(findindex(2)).Linked)]); + no=findindex(no); +elseif sumtempCaSc==3 + no = mymenu('In which image stack do you want to detect calcium?',['Image stack no ' num2str(SET(findindex(1)).Linked)], ['Image stack no ' num2str(SET(findindex(2)).Linked)],['Image stack no ' num2str(SET(findindex(3)).Linked)]); + no=findindex(no); + +end + + +callbackfunctions('calccalciummask',no,seg,1) + + + +%--------------------------- +function calccalciummask(no,seg,onORoff) %#ok +%--------------------------- +%Computes calciummask, will be replace by code from Lisa +radius1=[]; +global SET NO + +if nargin==0 + no = NO; +end +%segim=SET(seg).IM; +im=SET(no).IM; +im = calcfunctions('calctruedata',im,no); %g?r om till Hounsfieldunits +outputmask = uint8((im>=130)); + +imbin = (im>=130); %allt ?ver 130 Hu r?knas som kalk +imbin = squeeze(imbin); +bw = bwconncomp(imbin); + + +if bw.NumObjects>0 + for k=1:bw.NumObjects + thislist=bw.PixelIdxList{1,k}; + [R]=numel(thislist); + % Cascore i mm3 + Cascore1 = R*SET(no).ResolutionX*SET(no).ResolutionY*(SET(no).SliceThickness+SET(no).SliceGap); + if Cascore1>3 + outputmask(bw.PixelIdxList{k})=uint8(2); + end + + end +end + +SET(no).CT.CalciumMask = outputmask; +if seg~=0 +lengthsofthisIm=[]; +% Pick outsets of 4 or more +sizesetstruct=size(SET); + +threedvol=uint8(zeros(SET(seg).XSize,SET(seg).YSize,SET(seg).ZSize)); +threedvol2=uint8(zeros(SET(seg).XSize,SET(seg).YSize,SET(seg).ZSize)); +threedvolM=uint8(zeros(SET(seg).XSize,SET(seg).YSize,SET(seg).ZSize)); +threedvolA=uint8(zeros(SET(seg).XSize,SET(seg).YSize,SET(seg).ZSize)); +SET(no).CT.CalciumPenMask=uint8(zeros(SET(seg).XSize,SET(seg).YSize,SET(seg).ZSize)); +shortaxisImagelocation=0; +EXlocation= 0; + +for n=1:sizesetstruct(1,2) + + if strcmp(SET(n).ImageViewPlane,'Short-axis')==1 && contains(SET(n).SeriesDescription,'CaSc')==1 + shortaxisImagelocation=n; + end + + if isempty(SET(n).EndoX)==0 + EXlocation= n; + else + EXlocation= seg; + end + if strcmp(SET(n).ImageViewPlane,'Transversal')==1 && contains(SET(n).SeriesDescription,'CorASeq')==1 + transversalContrastLocation=n; + end +end + + +% kolla vid vilken slice k segmenteringen b?rjar + +sizeOfEndoSeg=size(SET(EXlocation).EndoX); +for k=1:sizeOfEndoSeg(1,3) + if isnan(SET(EXlocation).EndoX(:,:,k))==0 + hereIsNotNan=k; + break; + end +end + + + +% Mask making + +meanX=mean(SET(EXlocation).EndoX(:,:,hereIsNotNan)); +meanY=mean(SET(EXlocation).EndoY(:,:,hereIsNotNan)); + +%ta bild 8 snitt upp + +imbin1=[]; +imbin2=[]; +Cascore1=0; +Cascore2=0; + +firstZslice=hereIsNotNan-8; +lastZslice=hereIsNotNan+8; +mitsizes=[]; +for slice=firstZslice:lastZslice + + im1=imadjust(SET(EXlocation).IM(:,:,1,slice)); + + %ber?kna treshold + im1=calcfunctions('calctruedata',im1,EXlocation); %g?r om till Hounsfieldunits + iim=(im1+1024)/ max(max(im1+1024)); + JJ=imhist(iim); + minloc=178+find(JJ(179:230)==min(JJ(179:230))); + maxloc=153+find(JJ(154:minloc(1))==max(JJ(154:minloc(1)))); + if length(maxloc(end))>=1 && JJ(maxloc(end))>700 + T1=round((maxloc(end)+minloc(1))/2)/256; + else + T1=minloc(1)/256; + end + T=T1*max(max(im1+1024))-1024; + im2=im1>T; + im2=imfill(im2, 'holes'); + + imageSizeX =SET(EXlocation).YSize; + imageSizeY = SET(EXlocation).XSize; + %om slice>=hereIsNotNan anv?nd befintlig lv segmentering + if slice>=hereIsNotNan + finalmitralmask=zeros(imageSizeY,imageSizeX); + endoX=round(SET(EXlocation).EndoX(:,:,slice)); + endoY=round(SET(EXlocation).EndoY(:,:,slice)); + for l=1:numel(SET(EXlocation).EndoY(:,:,slice)) + finalmitralmask(endoX(l),endoY(l))=1; + end + + se = strel('square',10); + finalmitralmask=(imdilate(finalmitralmask,se)); + finalmitralmask=imfill(finalmitralmask); +% figure +% imshow(finalmitralmask) + else + %hitta kantpunkter + scanwidth=10; + + for k=1:100 + sumyXled=0; + + sumyXled= sum(im2(round(meanX)-scanwidth:round(meanX)+scanwidth, round(meanY)+k)); + + if sumyXled/(scanwidth*2)<0.5 + edgeX=round(meanY)+k; + break + end + end + + isedgeYcreated=0; + for k=1:100 + sumyYled=0; + sumyYled= sum(im2(round(meanX)+k, round(meanY)-scanwidth:round(meanY)+scanwidth)); + + if sumyYled/(scanwidth*2)<0.5 + edgeY=round(meanX)+k; + isedgeYcreated=1; + break + end + + end + + isedgeY2created=0; + for k=1:100 + sumyYled=0; + sumyYled= sum(im2(round(meanX)-k, round(meanY)-scanwidth:round(meanY)+scanwidth)); + + if sumyYled/(scanwidth*2)<0.5 + edgeY2=round(meanX)-k; + isedgeY2created=1; + break + end + end + + if isedgeY2created==0 || isedgeYcreated==0 + newmeanX=meanX; + else + newmeanX=(edgeY+edgeY2)/2; + end + meanX=newmeanX; + + %Create circlemask + imageSizeX =SET(EXlocation).YSize; + imageSizeY = SET(EXlocation).XSize; + [columnsInImage rowsInImage] = meshgrid(1:imageSizeX, 1:imageSizeY); + centerX = meanY; + centerY = meanX; + if isedgeYcreated==0 + radius = round(max([edgeX-meanY meanX-edgeY2])); + else + radius = round(max([edgeX-meanY edgeY-meanX])); + end + radius1=[radius1; radius]; + if radius<30 + radius=30; + end + if radius>55 + radius=55; + end + circlePixels = (rowsInImage - centerY).^2 ... + + (columnsInImage - centerX).^2 <= radius.^2; + + immm=imfuse(im2,circlePixels); + immm=im2.*circlePixels; + + linemask= columnsInImage> (round(meanY)-radius); + + + + L=bwlabel(im2.*linemask); + + centerpoints=[]; + centerdists=[]; + sizes=[]; + for k=1:max(max(L)) + [C,R]=find(L==k); + sizes= [sizes; length(R)]; + centerpoints=[centerpoints; mean(R) mean(C)]; + centerdists= [centerdists; sqrt((mean(R)-meanY)^2+(mean(C)-meanX)^2)]; + end + maxsize=max(sizes); + bigobjindex=sizes>(maxsize/4); + O=find(bigobjindex); + centerdists2=centerdists(O); + centerpoints2=centerpoints(O,:); + EndoObjNbr=find(centerdists==min(centerdists2)); + L= L==EndoObjNbr; + if maxsize>8000 + L=circlePixels; + end + mitsizes=[mitsizes maxsize]; + +% if sum(sum(L))>15000 +% [C,R]=find(L); +% xline=mean(R); +% linemask= columnsInImage> xline-radius; +% L=L.*linemask; +% L=bwlabel(L); +% centerpoints=[]; +% centerdists=[]; +% sizes=[]; +% for k=1:max(max(L)) +% [C,R]=find(L==k); +% sizes= [sizes; length(R)]; +% centerpoints=[centerpoints; mean(R) mean(C)]; +% centerdists= [centerdists; sqrt((mean(R)-meanY)^2+(mean(C)-meanX)^2)]; +% end +% maxsize=max(sizes); +% bigobjindex=sizes>(maxsize/2); +% O=find(bigobjindex); +% centerdists2=centerdists(O); +% centerpoints2=centerpoints(O,:); +% EndoObjNbr=find(centerdists==min(centerdists2)); +% L= L==EndoObjNbr; +% end + finalmitralmask=L; + + end + [yM,xM]=find(finalmitralmask); + + % Aortamask + + linemaskA= columnsInImage3000 + + se = strel('square',7); + L = imerode(L,se); + L=bwlabel(L>0); + iseroded=iseroded+1; + break + end + end + for k=1:max(max(L)) + if sum(sum(L==k))>3000 + + se = strel('square',7); + L = imerode(L,se); + L=bwlabel(L>0); + iseroded=iseroded+1; + break + end + end + centerpoints=[]; + centerdists=[]; + sizes=[]; + isitnegative=[]; + + for k=1:max(max(L)) + [C,R]=find(L==k); + sizes= [sizes; length(R)]; + centerpoints=[centerpoints; mean(R) mean(C)]; + centerdists= [centerdists; sqrt((mean(R)-pointtolookfor)^2+(mean(C)-meanX)^2)]; + isitnegative=[isitnegative; (mean(R)-pointtolookfor)<0]; + end + + maxsize=max(sizes); + bigobjindex=sizes>(maxsize/10); + O=find(bigobjindex); + centerdists2=centerdists(O); + centerpoints2=centerpoints(O,:); + if isitnegative(find(centerdists==min(centerdists2)))==0 + centerdists2=sort(unique(centerdists2)); + EndoObjNbr=find(centerdists==centerdists2(end-1)); + else + EndoObjNbr=find(centerdists==min(centerdists2)); + end + L2=L; + L= L==EndoObjNbr; + + if sum(sum(L))>8000 + + centerX = pointtolookfor; + centerY = meanX; + radius = 50; + circlePixels = (rowsInImage - centerY).^2 ... + + (columnsInImage - centerX).^2 <= radius.^2; + finalaortamask=L.*circlePixels; + else + finalaortamask=L ; + end + while iseroded>0 + finalaortamask= imdilate(finalaortamask,se); + iseroded=iseroded-1; + end + + % check if the mask is bad + + [RA,CA]=find(finalaortamask); + [RM,CM]=find(finalmitralmask); + + lengthsofthisIm=[lengthsofthisIm sqrt((pointtolookfor-max(CA))^2 + (meanX-mean( RA(find(CA==max(CA)))))^2)]; + + for i=1:length(CA) + dist(i) = sqrt((pointtolookfor-CA(i))^2 + (meanX-RA(i))^2) ; + end + + + + + if mean(RA)>mean(RM) + centerdists2=sort(unique(centerdists2)); + if length(centerdists2)>1 + centerdists2(1)=200; + end + EndoObjNbr=find(centerdists==min(centerdists2)); + +if sum(sum(L2==EndoObjNbr))>500 && min(dist(find(CA==max(CA))))>30 + L= L2==EndoObjNbr; + + if sum(sum(L))>8000 + + centerX = pointtolookfor; + centerY = meanX; + radius = 50; + circlePixels = (rowsInImage - centerY).^2 ... + + (columnsInImage - centerX).^2 <= radius.^2; + finalaortamask=L.*circlePixels; + else + finalaortamask=L ; + end + while iseroded>0 + finalaortamask= imdilate(finalaortamask,se); + iseroded=iseroded-1; + end +end + end + if min(dist(find(CA==max(CA))))>35 || slice>hereIsNotNan+3 + finalaortamask= finalaortamask*0; + end + sizeoA(slice-firstZslice+1)= sum(sum(finalaortamask)); +% if sum(sum(finalaortamask))>5500 +% finalaortamask= finalaortamask*0; +% end + + [yA,xA]=find(finalaortamask); + + + % Save to mask & Dilate + + outputmask2=uint8(((finalaortamask+finalmitralmask)>0)); + outputmaskMitral=uint8(((finalmitralmask)>0)); + outputmaskAortic=uint8(((finalaortamask)>0)); + + + simm=SET(seg).IM; +simm=squeeze(simm); +% if slice>=(hereIsNotNan-8) && slice<(hereIsNotNan+8) +% figure +% subplot(1,2,1) +% imagesc(simm(:,:,slice)) +% colormap('gray'); +% hold on +% +% [~,c] = contour((finalaortamask)>0); +% c.LineColor= [0 0 1]; +% +% [~,c] = contour((finalmitralmask)>0); +% c.LineColor= [1 0 0]; +% slice +% end + + + se = strel('square',20); + outputmask3=imfill(imdilate(outputmask2,se)); + outputmask2=edge(imfill(imdilate(outputmask2,se))); + + outputmaskMitral=imfill(imdilate(outputmaskMitral,se)); + outputmaskAortic=imfill(imdilate(outputmaskAortic,se)); + + [yM,xM]=find(outputmaskMitral); + [yA,xA]=find(outputmaskAortic); + + if isempty(max(xA)) + linemaskA= uint8(columnsInImage < min(xM)); + else + linemaskA= uint8(columnsInImage < max(xA)); + end + linemaskM= uint8(~linemaskA); + + threedvol(:,:,slice) = uint8(outputmask2); + threedvol2(:,:,slice) = uint8(outputmask3); + threedvolM(:,:,slice) = uint8(outputmask3.*linemaskM); + threedvolA(:,:,slice) = uint8(outputmask3.*linemaskA); + +% figure +% imagesc(segim(:,:,1,slice)) +% colormap('gray'); +% hold on +% +% [~,c] = contour((outputmask3.*linemaskA)>0); +% c.LineColor= [0 1 1]; [~,c] = contour((outputmask3.*linemaskM)>0); +% c.LineColor= [0 0 1]; plot(pointtolookfor,meanX,'o'); + + +end +h = waitbar(0,'Please wait.'); + +threedvol=uint8(threedvol); +outputmask2 = segment3dp.resamplestack(seg,no,threedvol,h); %edge +threedvol2=uint8(threedvol2); +outputmask3 = segment3dp.resamplestack(seg,no,threedvol2,h); +threedvolM=uint8(threedvolM); +outputmaskM = segment3dp.resamplestack(seg,no,threedvolM,h); +threedvolA=uint8(threedvolA); +outputmaskA = segment3dp.resamplestack(seg,no,threedvolA,h); + +close(h); + +[~,~,zet]=size(outputmask2); +if onORoff==0 + for i=1:zet + SET(no).CT.CalciumMask(:,:,1,i) =uint8(3)*uint8(uint8(SET(no).CT.CalciumMask(:,:,1,i))==2).*uint8(outputmask3(:,:,i))+ 4* uint8((outputmask2(:,:,i))); + end +elseif onORoff==1 + for i=1:zet + SET(no).CT.CalciumMask(:,:,1,i) =uint8(7)*uint8(uint8(SET(no).CT.CalciumMask(:,:,1,i))==2).*uint8(outputmaskM(:,:,i)) + uint8(6)*uint8(uint8(SET(no).CT.CalciumMask(:,:,1,i))==2).*uint8(outputmaskA(:,:,i)) + uint8(4)*uint8(outputmask2(:,:,i)); + end +end +end + + +disp('dsds'); + +%--------------------------- +function removeallcalciumsegmentation_Callback +%--------------------------- +%removes all calciumsegmentation + +global DATA SET NO +no=NO; +if ~isfield(SET(no).CT, 'CalciumMask') + myfailed('There is no calcium mask in this image stack'); + return +end + +threes=find (SET(no).CT.CalciumMask==3); +sixs=find (SET(no).CT.CalciumMask==6); +sevens=find(SET(no).CT.CalciumMask==7); +eights=find (SET(no).CT.CalciumMask==8); + +CalciumMask=SET(no).CT.CalciumMask; + +if ~isempty(threes) + CalciumMask(threes)=5; +end +if ~isempty(sixs) + CalciumMask(sixs)=5; +end +if ~isempty(sevens) + CalciumMask(sevens)=5; +end +if ~isempty(eights) + CalciumMask(eights)=5; +end + +SET(no).CT.CalciumMask=CalciumMask; + + +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); + +%--------------------------- +function removeallcalciumsegmentationonthisslice_Callback +%--------------------------- +%removes all calciumsegmentation + +global DATA SET NO +no=NO; +if ~isfield(SET(no).CT,'CalciumMask') + myfailed('There is no calcium mask in this image stack'); + return +end + +slice=SET(no).CurrentSlice; +threes=find (SET(no).CT.CalciumMask(:,:,1,slice)==3); +sixs=find (SET(no).CT.CalciumMask(:,:,1,slice)==6); +sevens=find(SET(no).CT.CalciumMask(:,:,1,slice)==7); +eights=find (SET(no).CT.CalciumMask(:,:,1,slice)==8); + +CalciumMask=SET(no).CT.CalciumMask(:,:,1,slice); + +if ~isempty(threes) + CalciumMask(threes)=5; +end +if ~isempty(sixs) + CalciumMask(sixs)=5; +end +if ~isempty(sevens) + CalciumMask(sevens)=5; +end +if ~isempty(eights) + CalciumMask(eights)=5; +end + +SET(no).CT.CalciumMask(:,:,1,slice)=CalciumMask; + + +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); diff --git a/source/cessfpmarsegmentation.p b/source/cessfpmarsegmentation.p index 5fac19e..d6b2e58 100644 Binary files a/source/cessfpmarsegmentation.p and b/source/cessfpmarsegmentation.p differ diff --git a/source/changelog.p b/source/changelog.p index e5c4eb3..1561768 100644 Binary files a/source/changelog.p and b/source/changelog.p differ diff --git a/source/checkdatabaselicense.p b/source/checkdatabaselicense.p index 840bcea..4cbc31d 100644 Binary files a/source/checkdatabaselicense.p and b/source/checkdatabaselicense.p differ diff --git a/source/checkpath.m b/source/checkpath.m index 2a682f3..9675a65 100644 --- a/source/checkpath.m +++ b/source/checkpath.m @@ -4,18 +4,74 @@ function checkpath(pathname) %path. %Einar Heiberg -if nargin<1 - [pathname] = fileparts(which('segment_main')); -end; -%get current path -p = path; +global DATA -if isempty(strfind(p,pathname)) - %Add to the path; - addpath(pathname); - if exist([pathname filesep 'tensorarray'],'dir') - addpath([pathname filesep 'tensorarray']); %Required by Vortex methods - addpath([pathname filesep 'tensorarray' filesep 'VortexMethods']); %Required by Vortex methods +if isdeployed() + + %Check if in correct path + if iscorrectpath(pathname) + return; end -end; + + %--- Ok. Not correct look in program files + programfilesdir = getenv('programfiles'); + + programnamenospace = DATA.ProgramName; + programnamenospace = programnamenospace(programnamenospace~=' '); + + softwarepath = [programfilesdir filesep 'Medviso' filesep programnamenospace filesep 'application']; + if iscorrectpath(softwarepath) + %Found it change path to this folder + cd(softwarepath); + return + end + + myfailed('Software started from another folder than where it was installed. Please adjust shortcut path.'); + +else + + if nargin<1 + [pathname] = fileparts(which('segment_main')); + end + + %get current path + p = path; + + if ~contains(p,pathname) + %Add to the path; + addpath(pathname); + if exist([pathname filesep 'tensorarray'],'dir') + addpath([pathname filesep 'tensorarray']); %Required by Vortex methods + addpath([pathname filesep 'tensorarray' filesep 'VortexMethods']); %Required by Vortex methods + end + end + +end + +%----------------------------------------- +function correct = iscorrectpath(pathname) +%----------------------------------------- +%Check if we are in the correct folder +global DATA + +correct = false; + +%--- Check if correct folder by finding ProgramName.exe +namenospace = DATA.ProgramName; +namenospace = namenospace(namenospace~=' '); +wantfile = [namenospace '.exe']; +f = dir(pathname); +foundit = false; +for loop = 1:length(f) + if ~f(loop).isdir + if strcmp(f(loop).name,wantfile) + foundit = true; + end + end +end + +if foundit + %We seem to be in the correct folder + correct = true; +end diff --git a/source/checkversion.m b/source/checkversion.m deleted file mode 100644 index 8aff87e..0000000 --- a/source/checkversion.m +++ /dev/null @@ -1,43 +0,0 @@ -function checkversion() - if isdeployed() - platform = mexext(); - else - platform = 'source'; - end - - versionnbr = parseversionstr(changelog); - try - address = java.net.InetAddress.getLocalHost; - IPaddress = char(address.getHostAddress); - [online_version] = myurlread(sprintf( ... - 'http://www.medviso.com/getversion.php?platform=%s&version=%d&ip=%s', ... - platform,versionnbr,IPaddress),750); %750 is 750ms timeout - catch %#ok - return - end - - online_version = str2double(online_version); - - try - if online_version <= versionnbr - return - end - catch %#ok - return - end - - c = mymenu('A new version is available', ... - 'Update now', ... - 'Ask again later'); - if c == 1 - mybrowser('http://www.medviso.com/products/segment/download/'); - end -end - -function r = parseversionstr(vstr) - tt = sscanf(vstr, '%d.%d R%d'); - if numel(tt) ~= 3 - error('SEGMENT:ERROR', 'Couldn''t parse version string'); - end - r = tt(3); -end \ No newline at end of file diff --git a/source/checkversion.p b/source/checkversion.p new file mode 100644 index 0000000..2469810 Binary files /dev/null and b/source/checkversion.p differ diff --git a/source/cinewindow.m b/source/cinewindow.m index ab3a9b0..7a45c2e 100644 --- a/source/cinewindow.m +++ b/source/cinewindow.m @@ -8,7 +8,7 @@ function cinewindow(varargin) else macro_helper(varargin{:}); feval(varargin{:}); -end; +end %------------ function init @@ -33,7 +33,7 @@ function cinewindow(varargin) %Start the timer start(DATA.CineTimer); -end; +end %------------------------ function update(varargin) @@ -47,20 +47,19 @@ function update(varargin) %length is 2. When called on setup the length is zero. try - set(DATA.Handles.cinetoolicon,'state','off'); stop(DATA.CineTimer); catch %#ok - end; + end DATA.CineTimer = []; try delete(DATA.Handles.cineaxes); catch %#ok - end; + end s = []; return; -end; +end if isempty(s) || isempty(varargin) %First call => init @@ -74,8 +73,8 @@ function update(varargin) try delete(DATA.Handles.cineaxes); catch - end; - end; + end + end DATA.Handles.cineaxes = axes('position',... [0.04 0.56 0.3 0.3],... %[0.05 0.68 0.3 0.3],... @@ -108,7 +107,7 @@ function update(varargin) %Buttondown set(s.imagehandle,'ButtondownFcn','cinewindow(''update'',''kill'')'); return; -end; +end %next update s.count = s.count+1; @@ -122,12 +121,12 @@ function update(varargin) %Get next slice f = 0.25; s.slice = 1+round((SET(s.no).ZSize-1)*rem(now*3600*24*f,1)); -end; +end -if s.count>40000; +if s.count>40000 update('kill'); return; -end; +end %Check if is handle if ishandle(s.imagehandle) @@ -135,4 +134,4 @@ function update(varargin) else update('kill'); return; -end; +end diff --git a/source/commandlinehelper.m b/source/commandlinehelper.m new file mode 100644 index 0000000..233068c --- /dev/null +++ b/source/commandlinehelper.m @@ -0,0 +1,143 @@ +function [varargout] = commandlinehelper(arg,varargin) +%Helper function to handle commandline options + +%Einar Heiberg + +persistent s %store options in persistent variable + +%--- Define commandline options +c = []; +c(1).switch = 'StudiesFolder'; c(1).nargin = 1; c(1).default = ''; c(1).description = ': folder software reads input files (dicoms), each subfolder is one series'; +c(2).switch = 'DICOMStorageFolder'; c(2).nargin = 1; c(2).default = ''; c(2).description = ': folder where output dicom files are stored'; +c(3).switch = 'LogFolder'; c(3).nargin = 1; c(3).default = ''; c(3).description = ': folder where log-files are stored'; +c(4).switch = 'NoQuit'; c(4).nargin = 0; c(4).default = false; c(4).description = ': Disable quit options'; +c(5).switch = 'NoPopUp'; c(5).nargin = 0; c(5).default = false; c(5).description = ': Disable pop-up when starting'; +c(6).switch = 'License'; c(6).nargin = 1; c(6).default = ''; c(6).description = ': License file'; +c(7).switch = 'TempStorageFolder'; c(7).nargin = 1; c(7).default = ''; c(7).description = ': folder for temporal file storage'; +c(8).switch = 'UseDefaultStudiesFolder'; c(8).nargin = 0; c(8).default = false; c(8).description = ': Create studies folder if it not existing according to default preference settings'; +c(9).switch = 'UseComputerAETitle'; c(9).nargin = 0; c(9).default = false; c(9).description = ': Use computer AETitle in case if in segpref was different one assigned'; +switch arg + case 'parse' + %do nothing here, do later after switch clause + case 'getparameters' + %return parameters + varargout = cell(1,1); + varargout{1} = s; + return + case 'storetopref' + %store settings to prefstruct + storetopref(s); + return; + case 'reset' + %reset persistent variable + s = []; + for loop = 1:length(c) + s.(c(loop).switch) = c(loop).default; + end + otherwise + error('Invalid options to commandlinehelper'); +end + +%--- parse clause + +if isempty(varargin) + return +end + +disp('------------------------------'); +disp('Parsing commandline options'); + +%Initialize s +s = []; +for loop = 1:length(c) + s.(c(loop).switch) = c(loop).default; +end + +%Add -help +n = length(c)+1; +c(n).switch = 'help'; c(n).nargin = 0; c(n).default = ''; + +%--- parse options +parameters = varargin; + +while ~isempty(parameters) + found = false; + thisparameter = parameters{1}; %first of parameters + if isequal(thisparameter,'-help') + displayhelp(c); + parameters = parameters(2:end); + else + %loop over to find + for loop = 1:length(c) + if isequal(['-' lower(c(loop).switch)],lower(thisparameter)) + found = true; + numargs = c(loop).nargin; + option = c(loop).switch; + if numargs==1 + arg = cleanstring(parameters{2}); %more than one argument not yet implemented + parameters = parameters(3:end); + disp(sprintf(' * %s=%s',c(loop).switch,arg)); %#ok + else + arg = true; %to indicate that it is found + parameters = parameters(2:end); + disp(sprintf(' * %s=true',c(loop).switch)); %#ok + end + + end + end + + if found + s.(option) = arg; %store it + else + %warn user + disp(sprintf(' * option %s not recognized, ignored.',thisparameter)); %#ok + parameters = parameters(2:end); %Remove parameters + end + + + end + +end + +disp('------------------------------'); + +%---------------------- +function displayhelp(c) +%---------------------- +%Displays helptext + +disp(sprintf('Help information, version %s',changelog)); %#ok +disp(' '); +for loop = 1:(length(c)-1) + disp(sprintf('-%s %s',lower(c(loop).switch),c(loop).description)); %#ok + disp(' '); +end + +%---------------------- +function storetopref(s) +%---------------------- +%Store settings to pref struct (DATA.Pref) + +global DATA + +if isempty(s) + return +end + +f = fieldnames(s); + +for loop = 1:length(f) + DATA.Pref.(f{loop}) = s.(f{loop}); +end + +%-------------------------------- +function stri = cleanstring(stri) +%-------------------------------- +%Cleans string from " signs + +%Remove " +stri = stri(stri~='"'); + +%Remove ' +c = ''''; +stri = stri(stri~=c); diff --git a/source/communicate.p b/source/communicate.p index e36b49c..c212676 100644 Binary files a/source/communicate.p and b/source/communicate.p differ diff --git a/source/createfunctions.m b/source/createfunctions.m new file mode 100644 index 0000000..f52ff8c --- /dev/null +++ b/source/createfunctions.m @@ -0,0 +1,839 @@ +function [varargout] = createfunctions(varargin) +% Functions for creating graphicsobjects and content in image panels +% Klas +%Invoke subfunction +macro_helper(varargin{:}); %future macro recording use +if (nargout) + [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard +else + feval(varargin{:}); % FEVAL switchyard +end + +%---------------------------------------------- +function addcolorbar(panel,contrast,brightness) %#ok +%---------------------------------------------- +%Add colorbar to axes in panel +global DATA SET + +if DATA.GUISettings.ShowColorbar + no = DATA.ViewPanels(panel); + if nargin < 2 + contrast = SET(no).IntensityMapping.Contrast; + brightness = SET(no).IntensityMapping.Brightness; + end + %addcolorbar + h = colorbar(DATA.Handles.imageaxes(panel),'East'); + + [win, level] = calcfunctions('con2win',contrast, brightness, no); + if ~isempty(win) && ~isempty(level) + set(DATA.Handles.imageaxes(panel),'CLim',[(level-win/2) (level+win/2)]) + else + colorbar(DATA.Handles.imageaxes(panel),'off') + return; + end + if isempty(SET(no).Colormap) + colormap(h,'gray'); + else + colormap(h,SET(no).Colormap); + end + h.Color = DATA.GUISettings.ForegroundColor; + %h.Limits = +else + %removecolorbar + colorbar(DATA.Handles.imageaxes(panel),'off') +end + +%--------------------- +function createplotoverlay %#ok +%----------------------- +%Creates graphical objects in volume and flow axes. +global DATA + + +DATA.Handles.volumeaxes.FontSmoothing = 'off'; +DATA.Handles.flowaxes.FontSmoothing = 'off'; +DATA.Handles.timebaraxes.FontSmoothing = 'off'; + + +volax = DATA.Handles.volumeaxes; +flowax = DATA.Handles.flowaxes; +timeax = DATA.Handles.timebaraxes; + +lc = DATA.GUISettings.BarColor; + +%time plot +ylim(DATA.Handles.timebaraxes, [0,1]); %always between 0 and 1 +DATA.Handles.timebar = line('Parent',timeax,'XData',nan,'YData',nan,'Color',lc,'linewidth',2); +DATA.Handles.timebaraxeshelpers=line('Parent',timeax,'XData',nan,'YData',nan,'Color','k'); +DATA.Handles.edtimebartext=text('Parent',timeax,'position',[nan nan],'color',lc,'String','ED'); +DATA.Handles.estimebartext=text('Parent',timeax,'position',[nan nan],'color',lc,'String','ES'); +DATA.Handles.edtimebarline=line('Parent',timeax,'XData',nan,'YData',nan,'Color',lc,'linewidth',2); +DATA.Handles.estimebarline=line('Parent',timeax,'XData',nan,'YData',nan,'Color',lc,'linewidth',2); +set([DATA.Handles.estimebartext DATA.Handles.estimebarline],'ButtonDownFcn','segment(''esedtimebar_Buttondown'',''es'')'); +set([DATA.Handles.edtimebartext DATA.Handles.edtimebarline],'ButtonDownFcn','segment(''esedtimebar_Buttondown'',''ed'')'); +set([DATA.Handles.timebar,timeax,DATA.Handles.timebaraxeshelpers],'buttondownFcn','segment(''timebar_Buttondown'')'); +set(timeax,'ytick',[]) +xlabel(timeax,dprintf('Time [ms]'),'color',DATA.GUISettings.VolumeAxesColor,'units','normalized'); +set(volax,... + 'XColor',DATA.GUISettings.VolumeAxesColor,... + 'YColor',DATA.GUISettings.VolumeAxesColor); + +%volume plot +DATA.Handles.timebarlv = line('Parent',volax,'XData',nan,'YData',nan,'Color',lc,'linewidth',2); +DATA.Handles.volumecurve = line('Parent',volax,'XData',nan,'YData',nan,'Color','r','markersize',5,'linestyle','-.'); +DATA.Handles.masscurve = line('Parent',volax,'XData',nan,'YData',nan,'Color','b','markersize',5,'linestyle','-.'); +DATA.Handles.rvvcurve = line('Parent',volax,'XData',nan,'YData',nan,'Color','m','markersize',5,'linestyle','-.'); +DATA.Handles.volumeaxeshelpers = line('Parent',volax,'XData',nan,'YData',nan,'Color','k'); +DATA.Handles.estext=text('Parent',volax,'position',[nan nan],'color',lc,'String','ES'); +DATA.Handles.edtext=text('Parent',volax,'position',[nan nan],'color',lc,'String','ED'); +DATA.Handles.esline= line('Parent',volax,'XData',nan,'YData',nan,'Color',lc); +DATA.Handles.edline= line('Parent',volax,'XData',nan,'YData',nan,'Color',lc); +DATA.Handles.lvmtext=text('Parent',volax,'position',[nan nan],'color','b','fontsize',8,'String','LVM','verticalalignment','bottom'); +set([DATA.Handles.estext,DATA.Handles.esline],'buttondownFcn','segment(''esed_Buttondown'',''es'')') +set([DATA.Handles.edtext,DATA.Handles.edline],'buttondownFcn','segment(''esed_Buttondown'',''ed'')') +set([volax, DATA.Handles.timebarlv,DATA.Handles.volumecurve,DATA.Handles.masscurve,DATA.Handles.rvvcurve,DATA.Handles.volumeaxeshelpers],... + 'buttondownFcn','segment(''volumeaxes_Buttondown'')') +ylabel(volax,dprintf('Volume [ml]'),'color',DATA.GUISettings.VolumeAxesColor,'units','normalized'); +xlabel(volax,dprintf('Time [ms]'),'color',DATA.GUISettings.VolumeAxesColor,'units','normalized'); +set(volax,... + 'XColor',DATA.GUISettings.VolumeAxesColor,... + 'YColor',DATA.GUISettings.VolumeAxesColor); + +%flow plot +DATA.Handles.timebarflow = line('Parent',flowax,'XData',nan,'YData',nan,'Color',lc,'linewidth',2); +DATA.Handles.outerbarsflow = line('Parent',flowax,'XData',nan,'YData',nan,'Color',lc,'linewidth',2); +DATA.Handles.zerolineflow = line('parent', flowax,'xdata',[0 10000000],'ydata',[0 0],'color','k','linestyle',':'); +DATA.Handles.flowcurve = line('Parent',flowax,'XData',nan,'YData',nan,'Color','b','markersize',5,'linestyle','-.'); +DATA.Handles.flowtext = text(nan,nan,'[Eddy]', ... + 'Parent',flowax,'FontSize',10,'HorizontalAlignment','right','VerticalAlignment','top','Color',DATA.GUISettings.ForegroundColor); +DATA.Handles.flowaxeshelpers = line('Parent',flowax,'XData',nan,'YData',nan,'Color','k'); +set([flowax,DATA.Handles.zerolineflow,DATA.Handles.flowcurve,DATA.Handles.flowaxeshelpers,DATA.Handles.outerbarsflow],... + 'ButtonDownFcn','segment(''flowaxes_Buttondown'')'); +ylabel(flowax,dprintf('Flow [ml/s]'),'color',DATA.GUISettings.VolumeAxesColor,'units','normalized'); +xlabel(flowax,dprintf('Time [ms]'),'color',DATA.GUISettings.VolumeAxesColor,'units','normalized'); +set(flowax,... + 'XColor',DATA.GUISettings.VolumeAxesColor,... + 'YColor',DATA.GUISettings.VolumeAxesColor); + +%--------------------- +function createaxes(rows,cols) %#ok +%----------------------- +%Creates imageaxes and boxaxes. The field boxaxes is probably unnecessary. +global DATA + +%Create 2 imageaxes +left = DATA.GUISettings.LeftGapWidth; %0.12; +right = 1-DATA.GUISettings.RightGapWidth-0.02; %Based on that the report panel can never be more than 220. +bottom = DATA.GUISettings.BottomGapHeight; %0.013; +top = 1-DATA.GUISettings.TopGapHeight; +width = right-left; +height = top-bottom; + +%Create image area with grid for boxes. +DATA.Handles.boxaxes = axes('position',... + [left bottom width height],... + 'parent',DATA.fig,'visible','off'); + +%2 => 0.5 +%3 => 0.333 0.666 +h = []; +hold(DATA.Handles.boxaxes,'on'); +for rloop=1:(rows-1) + h = [h;plot(DATA.Handles.boxaxes,[0 1],[1/rows*rloop 1/rows*rloop])];%,DATA.GUISettings.BoxAxesLineSpec)]; %#ok +end + +for cloop=1:(cols-1) + h = [h;plot(DATA.Handles.boxaxes,[1/cols*cloop 1/cols*cloop],[0 1])]; %#ok +end + +h = [h;plot(DATA.Handles.boxaxes,[0 1],[0 0])]; +h = [h;plot(DATA.Handles.boxaxes,[0 1],[1 1])]; +h = [h;plot(DATA.Handles.boxaxes,[0 0],[0 1])]; +h = [h;plot(DATA.Handles.boxaxes,[1 1],[0 1])]; +hold(DATA.Handles.boxaxes,'off'); +axis(DATA.Handles.boxaxes,'off'); +set(h,'color',[0.1,0.1,0.1],'linewidth',2); + +h = []; +for rloop=(rows-1):-1:0 + for cloop=0:(cols-1) + h = [h axes('position',... + [left+cloop*width/cols bottom+rloop*height/rows width/cols height/rows],... + 'parent',DATA.fig,'visible','off')]; %#ok + end +end + +%Store handles +axis(h,'ij') +set(h,'fontsmoothing','off') +DATA.Handles.imageaxes = h; + +%--------------------- +function createaxesandimagehandles(maxnumaxes) %#ok +%----------------------- +%Creates the maximum used imageaxes and boxaxes in segment. The field boxaxes is probably unnecessary. +global DATA + +% %Sizes in which we place the panels +% left = DATA.GUISettings.LeftGapWidth; %0.12; +% right = 1-DATA.GUISettings.RightGapWidth-0.02; %Based on that the report panel can never be more than 220. +% bottom = DATA.GUISettings.BottomGapHeight; %0.013; +% top = 1-DATA.GUISettings.TopGapHeight; +% width = right-left; +% height = top-bottom; + +%Create image area with grid for boxes. +DATA.Handles.boxaxes = axes('position',... + [0 0 0 0],'color',[0.1,0.1,0.1],... + 'parent',DATA.fig,'visible','off'); + +%This is the line in boxaxes which actually makeup the box around all the panels +DATA.Handles.box = line('parent',DATA.Handles.boxaxes,'XData',nan,'YData',nan,'linewidth',2); + +%create empty axes +h = []; +for i = 1:maxnumaxes + h = [h axes('position',... + [0 0 0 0],... + 'parent',DATA.fig,'visible','off')]; %#ok +end + +%Store handles +axis(h,'ij') +set(h,'fontsmoothing','off') +DATA.Handles.imageaxes = h; + +%Initiate imagehandles in all axes +DATA.Handles.imagehandles = gobjects(1,maxnumaxes); +for i = 1:maxnumaxes + DATA.Handles.imagehandles(i) = image('parent',DATA.Handles.imageaxes(i),'cdata',[]); +end + +%Create sliders (used in 3DPrint for scrolling) +h = []; +for i = 1:maxnumaxes + h = [h uicontrol('Style','slider','parent',DATA.fig,'visible','off')]; %#ok +end +DATA.Handles.sliders = h; + +%----------------------------------- +function create3dpoverlay %#ok +%----------------------------------- +global DATA +%Draws and initiates all necessary handles for 3dp viewpanels + +%for 3DP the maximum number of panels are +maxnumpanels = 4; +emptygraphics = gobjects(1,maxnumpanels); +DATA.Handles.rbline = emptygraphics; +DATA.Handles.rgline = emptygraphics; +DATA.Handles.grline = emptygraphics; +DATA.Handles.gbline = emptygraphics; +DATA.Handles.brline = emptygraphics; +DATA.Handles.bgline = emptygraphics; +DATA.Handles.threedpcontour = emptygraphics; + +for i = 1:maxnumpanels + DATA.Handles.rbline(i) = line('parent',DATA.Handles.imageaxes(i),'XData',[nan nan],'YData',[nan nan],'Color','b','lineStyle','-'); %add lines, later correct in lineupdate; + DATA.Handles.rgline(i) = line('parent',DATA.Handles.imageaxes(i),'XData',[nan nan],'YData',[nan nan],'Color','g','lineStyle','-'); + + DATA.Handles.grline(i) = line('parent',DATA.Handles.imageaxes(i),'XData',[nan nan],'YData',[nan nan],'Color','r','lineStyle','-'); + DATA.Handles.gbline(i) = line('parent',DATA.Handles.imageaxes(i),'XData',[nan nan],'YData',[nan nan],'Color','b','lineStyle','-'); + + DATA.Handles.brline(i) = line('parent',DATA.Handles.imageaxes(i),'XData',[nan nan],'YData',[nan nan],'Color','r','lineStyle','-'); + DATA.Handles.bgline(i) = line('parent',DATA.Handles.imageaxes(i),'XData',[nan nan],'YData',[nan nan],'Color','g','lineStyle','-'); + hold(DATA.Handles.imageaxes(i),'on') + warning('off') %we are fine with the contour not being rendered and only created here + + [~,DATA.Handles.threedpcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[127 127]); + DATA.Handles.threedpcontour(i).LineColor = 'g'; + + warning('on') + hold(DATA.Handles.imageaxes(i),'off') +end + + +%--------------------- +function createimageoverlayall %#ok +%----------------------- +%This function initiates all overlay graphics such as text contours etc. +% profile on + +global DATA +maxnumpanels = length(DATA.Handles.imageaxes); +% the initial test should be with contours measurement lines and measurement text as these +% are the most complex cases. +DATA.imagecursor =gobjects(1,1); + +emptygraphics = gobjects(1,maxnumpanels); +DATA.Handles.endocontour = emptygraphics; +DATA.Handles.epicontour = emptygraphics; +DATA.Handles.rvendocontour = emptygraphics; +DATA.Handles.rvepicontour = emptygraphics; +DATA.Handles.endointerp = emptygraphics; +DATA.Handles.epiinterp = emptygraphics; +DATA.Handles.rvendointerp = emptygraphics; +DATA.Handles.rvepiinterp = emptygraphics; +DATA.Handles.generalpeninterp = emptygraphics; +DATA.Handles.generalpencontour = emptygraphics; +DATA.Handles.scarcontour = emptygraphics; +DATA.Handles.marcontour = emptygraphics; +DATA.Handles.weightedscarcontour = emptygraphics; %Weighted scar contour +DATA.Handles.mocontour = emptygraphics; %microvascular obstruction contour +DATA.Handles.moextentcontour = emptygraphics; %microvascular obstruction contour +DATA.Handles.selectedslice = emptygraphics; %handle to yellow box sourrounding selected slices +DATA.Handles.selectedframe = emptygraphics; +DATA.Handles.cursor = gobjects(1); % this is the temporary line used when drawing with the pen tool + +DATA.Handles.centercross = emptygraphics; %handle to the center cross, visible in Segment + +DATA.Handles.endocontourintersection = emptygraphics; +DATA.Handles.epicontourintersection = emptygraphics; +DATA.Handles.rvendocontourintersection = emptygraphics; +DATA.Handles.rvepicontourintersection = emptygraphics; +DATA.Handles.text = emptygraphics; + +DATA.Handles.planeintersection = gobjects(maxnumpanels); + +%DATA.Handles.roi = gobjects(length(DATA.ViewPanels),50); %cannot have more than 20 rois in a panel +maxnumberofrois = 10; +DATA.Handles.broi = emptygraphics; % +DATA.Handles.croi = emptygraphics; % +DATA.Handles.groi = emptygraphics; % +DATA.Handles.rroi = emptygraphics; % +DATA.Handles.kroi = emptygraphics; % +DATA.Handles.mroi = emptygraphics; % +DATA.Handles.yroi = emptygraphics; % +DATA.Handles.wroi = emptygraphics; % +DATA.Handles.roicurrent = emptygraphics; %Current selected roi +% % % DATA.Handles.broitext = gobjects(maxnumpanels,maxnumberofrois);% +% % % DATA.Handles.croitext = gobjects(maxnumpanels,maxnumberofrois); % +% % % DATA.Handles.groitext = gobjects(maxnumpanels,maxnumberofrois);% +% % % DATA.Handles.rroitext = gobjects(maxnumpanels,maxnumberofrois);% +% % % DATA.Handles.kroitext = gobjects(maxnumpanels,maxnumberofrois);% +% % % DATA.Handles.mroitext = gobjects(maxnumpanels,maxnumberofrois);% +% % % DATA.Handles.yroitext = gobjects(maxnumpanels,maxnumberofrois);% +% % % DATA.Handles.wroitext = gobjects(maxnumpanels,maxnumberofrois);% + +% DATA.Handles.roitext = gobjects(length(DATA.ViewPanels),20); +DATA.Handles.measurement = emptygraphics; +DATA.Handles.measurementoutsideplane = emptygraphics; +DATA.Handles.measurementtext = gobjects(maxnumpanels,20);%cannot have more than 20 measurement texts in a panel +DATA.Handles.point = emptygraphics; +DATA.Handles.pointtext = gobjects(maxnumpanels,20);%cannot have more than 20 Point texts in a panel +DATA.Handles.orthoanglehandle = gobjects(1); + +%imagecursor is global used in toggleplaceholdermotion to draw custom pen +DATA.imagecursor =gobjects(1); +DATA.imagecursor = line('xdata',nan,'ydata',nan,'color','y'); + +%then we need to assert it's a line, text etc + +%the cursor and orthoanglehandle parents are set on the fly. But so that +%they arent initiated in loading interfaces where +DATA.Handles.cursor = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(1)); +DATA.Handles.orthoanglehandle = line('xdata',nan,'ydata',nan,'color','m','marker','.','MarkerSize',20,'parent',DATA.Handles.imageaxes(1)); + +%%% fix to copy object handles instead of creating in a loop +DATA.Handles.generalpencontour = (copyobj(line('xdata',nan,'ydata',nan,'color','y'),DATA.Handles.imageaxes))'; +DATA.Handles.endocontour = (copyobj(line('xdata',nan,'ydata',nan,'color','r'),DATA.Handles.imageaxes))'; +DATA.Handles.epicontour = (copyobj(line('xdata',nan,'ydata',nan,'color','g'),DATA.Handles.imageaxes))'; +DATA.Handles.rvendocontour = (copyobj(line('xdata',nan,'ydata',nan,'color','m'),DATA.Handles.imageaxes))'; +DATA.Handles.rvepicontour = (copyobj(line('xdata',nan,'ydata',nan,'color','c'),DATA.Handles.imageaxes))'; +DATA.Handles.measurement = (copyobj(line('xdata',nan,'ydata',nan,'color','y','marker','+'),DATA.Handles.imageaxes))'; +DATA.Handles.measurementoutsideplane = (copyobj(line('xdata',nan,'ydata',nan,'color','k','marker','+','linestyle','none'),DATA.Handles.imageaxes))'; +DATA.Handles.point = (copyobj(line('xdata',nan,'ydata',nan,'color','y','marker','+','linestyle','none'),DATA.Handles.imageaxes))'; +DATA.Handles.point3D = (copyobj(line('xdata',nan,'ydata',nan,'color','y','marker','o','linestyle','none'),DATA.Handles.imageaxes))'; +DATA.Handles.ortholines = (copyobj(line('xdata',nan,'ydata',nan,'color','w'),DATA.Handles.imageaxes))'; +DATA.Handles.selectedortholine = (copyobj(line('xdata',nan,'ydata',nan,'color','y'),DATA.Handles.imageaxes))'; +DATA.Handles.centercross = (copyobj(line('xdata',nan,'ydata',nan,'color','w','marker','+','MarkerSize',5,'linestyle','none'),DATA.Handles.imageaxes))'; + +%rois and measurements are special +DATA.Handles.roicurrent = (copyobj(line('xdata',nan,'ydata',nan,'color','b','linewidth',2),DATA.Handles.imageaxes))'; +DATA.Handles.broi = (copyobj(line('xdata',nan,'ydata',nan,'color','b','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.mroi = (copyobj(line('xdata',nan,'ydata',nan,'color','m','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.croi = (copyobj(line('xdata',nan,'ydata',nan,'color','c','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.groi = (copyobj(line('xdata',nan,'ydata',nan,'color','g','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.yroi = (copyobj(line('xdata',nan,'ydata',nan,'color','y','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.wroi = (copyobj(line('xdata',nan,'ydata',nan,'color','w','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.rroi = (copyobj(line('xdata',nan,'ydata',nan,'color','r','linewidth',1),DATA.Handles.imageaxes))'; +DATA.Handles.kroi = (copyobj(line('xdata',nan,'ydata',nan,'color','k','linewidth',1),DATA.Handles.imageaxes))'; + +DATA.Handles.roitext = gobjects(maxnumpanels,maxnumberofrois); +for j = 1:maxnumberofrois +% % % for c = 'rgbymkwc' +% % % DATA.Handles.([c,'roitext'])(:,j) = (copyobj(text(nan,nan,'','HorizontalAlignment', 'right', ... +% % % 'VerticalAlignment', 'middle','color',[1,1,1],'clipping','on','fontsmoothing','off'),DATA.Handles.imageaxes))'; +% % % end + DATA.Handles.roitext(:,j) = (copyobj(text(nan,nan,'','HorizontalAlignment', 'right', ... + 'VerticalAlignment', 'middle','color',[1,1,1],'clipping','on','fontsmoothing','off'),DATA.Handles.imageaxes))'; +end + +for j = 1:20 + DATA.Handles.measurementtext(:,j) = (copyobj(text(nan,nan,'','FontWeight','bold','interpreter','none','HorizontalAlignment', 'left', ... + 'VerticalAlignment', 'middle','color','y','clipping','on','fontsmoothing','off'),DATA.Handles.imageaxes))'; + DATA.Handles.pointtext(:,j) = (copyobj(text(nan,nan,'','FontWeight','bold','interpreter','none','HorizontalAlignment', 'left', ... + 'VerticalAlignment', 'middle','color','w','clipping','on','fontsmoothing','off'),DATA.Handles.imageaxes))'; +end +for j = 1:maxnumpanels + DATA.Handles.planeintersection(:,j) = (copyobj(line('xdata',nan,'ydata',nan,'color','w'),DATA.Handles.imageaxes))'; +end + +%text entries +DATA.Handles.text = (copyobj(text(3,3,'','HorizontalAlignment', 'left', ... + 'VerticalAlignment', 'top','color',[1,1,1], 'Interpreter', 'none','fontsmoothing','off'),DATA.Handles.imageaxes))'; + +%selected slices handle +DATA.Handles.selectedslice = (copyobj(line('xdata',nan,'ydata',nan,'color','y','linewidth',1.5),DATA.Handles.imageaxes))'; +DATA.Handles.selectedframe = (copyobj(line('xdata',nan,'ydata',nan,'color','w','linewidth',1.5),DATA.Handles.imageaxes))'; +%%% end of fix: copy objects + +for i = 1:maxnumpanels +% DATA.Handles.generalpencontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y'); +% DATA.Handles.endocontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','r'); +% DATA.Handles.epicontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','g'); +% DATA.Handles.rvendocontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','m'); +% DATA.Handles.rvepicontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','c'); +% DATA.Handles.measurement(i) = line('xdata',nan,'ydata',nan,'color','y','marker','+','parent',DATA.Handles.imageaxes(i)); +% DATA.Handles.point(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','marker','+','linestyle','none'); +% DATA.Handles.point3D(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','marker','o','linestyle','none'); +% DATA.Handles.ortholines(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w'); +% DATA.Handles.selectedortholine(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y'); +% DATA.Handles.centercross(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w','marker','+','MarkerSize',5,'linestyle','none'); +% for j = 1:maxnumpanels +% DATA.Handles.planeintersection(i,j) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w'); +% end + +% %rois and measurements are special +% DATA.Handles.roicurrent(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','b','linewidth',2); +% DATA.Handles.broi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','b','linewidth',1); +% DATA.Handles.mroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','m','linewidth',1); +% DATA.Handles.croi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','c','linewidth',1); +% DATA.Handles.groi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','g','linewidth',1); +% DATA.Handles.yroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','linewidth',1); +% DATA.Handles.wroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w','linewidth',1); +% DATA.Handles.rroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','r','linewidth',1); +% DATA.Handles.kroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','k','linewidth',1); + + +% for j = 1:10 +% for c = 'rgbymkwc' +% DATA.Handles.([c,'roitext'])(i,j) = text(nan,nan,'','HorizontalAlignment', 'right', ... +% 'VerticalAlignment', 'middle','color',[1,1,1], 'parent',DATA.Handles.imageaxes(i),'clipping','on','fontsmoothing','off'); +% end +% end +% for j = 1:20 +% DATA.Handles.measurementtext(i,j) = text(nan,nan,'','FontWeight','bold','interpreter','none','HorizontalAlignment', 'left', ... +% 'VerticalAlignment', 'middle','color','y', 'parent',DATA.Handles.imageaxes(i),'clipping','on','fontsmoothing','off'); +% DATA.Handles.pointtext(i,j) = text(nan,nan,'','FontWeight','bold','interpreter','none','HorizontalAlignment', 'left', ... +% 'VerticalAlignment', 'middle','color','w', 'parent',DATA.Handles.imageaxes(i),'clipping','on','fontsmoothing','off'); +% end + + %plot commands delete axes content if not hold is toggled on + hold(DATA.Handles.imageaxes(i),'on') + + warning('off') %we are fine with the contour not being rendered and only created here + [~,DATA.Handles.scarcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.scarcontour(i).LineColor = [1 1 0]; + + [~,DATA.Handles.weightedscarcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.weightedscarcontour(i).LineColor = [1 0.5 0.5]; + + [~,DATA.Handles.mocontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.mocontour(i).LineColor = [1 0 0]; + DATA.Handles.mocontour(i).LineStyle = ':'; + + [~,DATA.Handles.moextentcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.99 0.99]); + DATA.Handles.moextentcontour(i).LineColor = [1 0 0]; + + [~,DATA.Handles.marcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.marcontour(i).LineColor = [1 1 1]; + warning('on') + + %interp allocation + DATA.Handles.endointerp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','r','MarkerSize',12,'linestyle','none'); + DATA.Handles.epiinterp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','g','MarkerSize',12,'linestyle','none'); + DATA.Handles.rvendointerp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','m','MarkerSize',12,'linestyle','none'); + DATA.Handles.rvepiinterp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','c','MarkerSize',12,'linestyle','none'); + DATA.Handles.generalpeninterp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','y','MarkerSize',12,'linestyle','none'); + + %intersections + DATA.Handles.endocontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','r','MarkerSize',5,'linestyle','none'); + DATA.Handles.epicontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','g','MarkerSize',5,'linestyle','none'); + DATA.Handles.rvendocontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','m','MarkerSize',5,'linestyle','none'); + DATA.Handles.rvepicontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','c','MarkerSize',5,'linestyle','none'); + hold(DATA.Handles.imageaxes(i),'off') + +% %text entries +% DATA.Handles.text(i) = text(3,3,'','HorizontalAlignment', 'left', ... +% 'VerticalAlignment', 'top','color',[1,1,1], 'parent',DATA.Handles.imageaxes(i), 'Interpreter', 'none','fontsmoothing','off'); +% +% %selected slices handle +% DATA.Handles.selectedslice(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','linewidth',1.5); +% DATA.Handles.selectedframe(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w','linewidth',1.5); + +end +% profile report + + + +%--------------------- +function createimages %#ok +%----------------------- +%Initiates all imagehandles +global DATA + +%Initiate imagehandles in all axes +DATA.Handles.imagehandles = gobjects(1,length(DATA.ViewPanels)); +for i = 1:length(DATA.ViewPanels) + DATA.Handles.imagehandles(i) = image('parent',DATA.Handles.imageaxes(i),'cdata',[]); +end + +%--------------------- +function createplot %#ok +%----------------------- +global DATA + + +DATA.Handles.plot1 = line('xdata',nan,'ydata',nan,'color','r','parent',DATA.Handles.plotaxes); +DATA.Handles.plot2 = line('xdata',nan,'ydata',nan,'color','g','parent',DATA.Handles.plotaxes); +DATA.Handles.plot3 = line('xdata',nan,'ydata',nan,'color','b','parent',DATA.Handles.plotaxes); +DATA.Handles.plot4 = line('xdata',nan,'ydata',nan,'color','c','parent',DATA.Handles.plotaxes); + +%--------------------- +function createimageoverlay %#ok +%----------------------- +%This function initiates all overlay graphics such as text contours etc. +global DATA + +% the initial test should be with contours measurement lines and measurement text as these +% are the most complex cases. +emptygraphics = gobjects(1,length(DATA.ViewPanels)); +DATA.Handles.endocontour = emptygraphics; +DATA.Handles.epicontour = emptygraphics; +DATA.Handles.rvendocontour = emptygraphics; +DATA.Handles.rvepicontour = emptygraphics; +DATA.Handles.endointerp = emptygraphics; +DATA.Handles.epiinterp = emptygraphics; +DATA.Handles.rvendointerp = emptygraphics; +DATA.Handles.rvepiinterp = emptygraphics; +DATA.Handles.generalpeninterp = emptygraphics; +DATA.Handles.generalpencontour = emptygraphics; +DATA.Handles.scarcontour = emptygraphics; +DATA.Handles.marcontour = emptygraphics; +DATA.Handles.weightedscarcontour = emptygraphics; %Weighted scar contour +DATA.Handles.mocontour = emptygraphics; %microvascular obstruction contour +DATA.Handles.moextentcontour = emptygraphics; %microvascular obstruction contour +DATA.Handles.selectedslice = emptygraphics; %handle to yellow box sourrounding selected slices +DATA.Handles.selectedframe = emptygraphics; +DATA.Handles.cursor = gobjects(1); % this is the temporary line used when drawing with the pen tool + +DATA.Handles.endocontourintersection = emptygraphics; +DATA.Handles.epicontourintersection = emptygraphics; +DATA.Handles.rvendocontourintersection = emptygraphics; +DATA.Handles.rvepicontourintersection = emptygraphics; +DATA.Handles.text = emptygraphics; + +DATA.Handles.planeintersection = gobjects(length(DATA.ViewPanels)); + +DATA.Handles.centercross = emptygraphics; %handle to the center cross, visible in Segment + +%DATA.Handles.roi = gobjects(length(DATA.ViewPanels),50); %cannot have more than 20 rois in a panel +DATA.Handles.broi = emptygraphics; % +DATA.Handles.croi = emptygraphics; % +DATA.Handles.groi = emptygraphics; % +DATA.Handles.rroi = emptygraphics; % +DATA.Handles.kroi = emptygraphics; % +DATA.Handles.mroi = emptygraphics; % +DATA.Handles.yroi = emptygraphics; % +DATA.Handles.wroi = emptygraphics; % +DATA.Handles.roicurrent = emptygraphics; %Current selected roi +DATA.Handles.broitext = gobjects(length(DATA.ViewPanels),20);% +DATA.Handles.croitext = gobjects(length(DATA.ViewPanels),20); % +DATA.Handles.groitext = gobjects(length(DATA.ViewPanels),20);% +DATA.Handles.rroitext = gobjects(length(DATA.ViewPanels),20);% +DATA.Handles.kroitext = gobjects(length(DATA.ViewPanels),20);% +DATA.Handles.mroitext = gobjects(length(DATA.ViewPanels),20);% +DATA.Handles.yroitext = gobjects(length(DATA.ViewPanels),20);% +DATA.Handles.wroitext = gobjects(length(DATA.ViewPanels),20);% + +% DATA.Handles.roitext = gobjects(length(DATA.ViewPanels),20); +DATA.Handles.measurement = emptygraphics; +DATA.Handles.measurementoutsideplane = emptygraphics; +DATA.Handles.measurementtext = gobjects(length(DATA.ViewPanels),20);%cannot have more than 20 measurement texts in a panel +DATA.Handles.point = emptygraphics; +DATA.Handles.pointtext = gobjects(length(DATA.ViewPanels),20);%cannot have more than 20 Point texts in a panel +DATA.Handles.orthoanglehandle = gobjects(1); +DATA.Handles.point3D = emptygraphics; %handle to the points in 3D + +%then we need to assert it's a line, text etc + +%the cursor and orthoanglehandle parents are set on the fly. But so that +%they arent initiated in loading interfaces where +DATA.Handles.cursor = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(1)); +DATA.Handles.orthoanglehandle = line('xdata',nan,'ydata',nan,'color','m','marker','.','MarkerSize',20,'parent',DATA.Handles.imageaxes(1)); + +%Use preferences linewidth if there +if ~isempty(DATA.Pref.LineWidth) + linewidth = DATA.Pref.LineWidth; +else + linewidth = 1; +end + +for i = 1:length(DATA.ViewPanels) + DATA.Handles.generalpencontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y'); + DATA.Handles.endocontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','r', 'LineWidth', linewidth); + DATA.Handles.epicontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','g', 'LineWidth', linewidth); + DATA.Handles.rvendocontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','m', 'LineWidth', linewidth); + DATA.Handles.rvepicontour(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','c', 'LineWidth', linewidth); + DATA.Handles.measurement(i) = line('xdata',nan,'ydata',nan,'color','y','marker','+','parent',DATA.Handles.imageaxes(i)); + DATA.Handles.measurementoutsideplane(i) = line('xdata',nan,'ydata',nan,'color','k','marker','+','parent',DATA.Handles.imageaxes(i)); %used to plot points outside the slice + DATA.Handles.point(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','marker','+','linestyle','none'); + DATA.Handles.ortholines(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w'); + DATA.Handles.selectedortholine(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y'); + + for j = 1:length(DATA.ViewPanels) + DATA.Handles.planeintersection(i,j) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w'); + end + + %rois and measurements are special + DATA.Handles.roicurrent(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','b','linewidth',linewidth+1); + DATA.Handles.broi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','b','linewidth',linewidth); + DATA.Handles.mroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','m','linewidth',linewidth); + DATA.Handles.croi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','c','linewidth',linewidth); + DATA.Handles.groi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','g','linewidth',linewidth); + DATA.Handles.yroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','linewidth',linewidth); + DATA.Handles.wroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w','linewidth',linewidth); + DATA.Handles.rroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','r','linewidth',linewidth); + DATA.Handles.kroi(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','k','linewidth',linewidth); + + for j = 1:20 + for c = 'rgbymkwgc' + DATA.Handles.([c,'roitext'])(i,j) = text(nan,nan,'','HorizontalAlignment', 'right', ... + 'VerticalAlignment', 'middle','color',[1,1,1], 'parent',DATA.Handles.imageaxes(i),'clipping','on'); + end + DATA.Handles.measurementtext(i,j) = text(nan,nan,'','FontWeight','bold','interpreter','none','HorizontalAlignment', 'left', ... + 'VerticalAlignment', 'middle','color','y', 'parent',DATA.Handles.imageaxes(i),'clipping','on'); + DATA.Handles.pointtext(i,j) = text(nan,nan,'','FontWeight','bold','interpreter','none','HorizontalAlignment', 'left', ... + 'VerticalAlignment', 'middle','color','w', 'parent',DATA.Handles.imageaxes(i),'clipping','on'); + end + + %plot commands delete axes content if not hold is toggled on + hold(DATA.Handles.imageaxes(i),'on') + + warning('off') %we are fine with the contour not being rendered and only created here + [~,DATA.Handles.scarcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.scarcontour(i).LineColor = [1 1 0]; + DATA.Handles.scarcontour(i).LineWidth = linewidth; + + [~,DATA.Handles.weightedscarcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.weightedscarcontour(i).LineColor = [1 0.5 0.5]; + + [~,DATA.Handles.mocontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.mocontour(i).LineColor = [1 0 0]; + DATA.Handles.mocontour(i).LineStyle = ':'; + + [~,DATA.Handles.moextentcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.99 0.99]); + DATA.Handles.moextentcontour(i).LineColor = [1 0 0]; + + [~,DATA.Handles.marcontour(i)] = contour(DATA.Handles.imageaxes(i),nan(2),[0.5 0.5]); + DATA.Handles.marcontour(i).LineColor = [1 1 1]; + DATA.Handles.marcontour(i).LineWidth = linewidth; + warning('on') + + %interp allocation + DATA.Handles.endointerp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','r','MarkerSize',12,'linestyle','none'); + DATA.Handles.epiinterp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','g','MarkerSize',12,'linestyle','none'); + DATA.Handles.rvendointerp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','m','MarkerSize',12,'linestyle','none'); + DATA.Handles.rvepiinterp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','c','MarkerSize',12,'linestyle','none'); + DATA.Handles.generalpeninterp(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'marker','.','color','y','MarkerSize',12,'linestyle','none'); + + %intersections + DATA.Handles.endocontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','r','MarkerSize',4,'linestyle','none'); + DATA.Handles.epicontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','g','MarkerSize',4,'linestyle','none'); + DATA.Handles.rvendocontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','m','MarkerSize',4,'linestyle','none'); + DATA.Handles.rvepicontourintersection(i) = line(DATA.Handles.imageaxes(i),nan,nan,'marker','.','color','c','MarkerSize',4,'linestyle','none'); + hold(DATA.Handles.imageaxes(i),'off') + + %text entries + DATA.Handles.text(i) = text(3,3,'','HorizontalAlignment', 'left', ... + 'VerticalAlignment', 'top','color',[1,1,1], 'parent',DATA.Handles.imageaxes(i), 'Interpreter', 'none'); + + %selected slices handle + DATA.Handles.selectedslice(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','y','linewidth',1.5); + DATA.Handles.selectedframe(i) = line('xdata',nan,'ydata',nan,'parent',DATA.Handles.imageaxes(i),'color','w','linewidth',1.5); + +end + +%-------------------------------- +function im = createviewim(panel) %#ok +%-------------------------------- +%Initiates all imagehandles and creates DATA.viewim which holds the current slice for all timeframes mapped ready for display. +global DATA SET + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); + +%Check if calcium score overlay +calciumim = []; +if isfield(SET(no),'CT') && isfield(SET(no).CT,'CalciumMask') + calciumoverlay = true; +else + calciumoverlay = false; +end + +% check for papillary muscle overlay +stateandicon=viewfunctions('iconson','hidelv'); +ispapmusc = false; +if not(stateandicon{1}) && (~isempty(SET(no).PapillaryIM)) + ispapmusc = true; +end + +%Later also have a hide function for this :-) + +switch DATA.ViewPanelsType{panel} + case 'trans3DP' + %im = drawfunctions('getoverlayimage','r'); + DATA.ViewIM{panel} = 'cache not used'; + %set zoom and aspectratio for axes + viewfunctions('updatezoomandaspectratio',panel); + return + case 'sag3DP' + %im = drawfunctions('getoverlayimage','g'); + DATA.ViewIM{panel} = 'cache not used'; + %set zoom and aspectratio for axes + viewfunctions('updatezoomandaspectratio',panel); + return + case 'cor3DP' + %im = drawfunctions('getoverlayimage','b'); + DATA.ViewIM{panel} = 'cache not used'; + %set zoom and aspectratio for axes + viewfunctions('updatezoomandaspectratio',panel); + return + case 'speedim' + DATA.ViewIM{panel} = 'cache not used'; + %set zoom and aspectratio for axes + viewfunctions('updatezoomandaspectratio',panel); + return + case 'viewport' + return; + case {'one','orth'} + im = SET(no).IM(:,:,:,SET(DATA.ViewPanels(panel)).CurrentSlice); + if calciumoverlay + calciumim = SET(no).CT.CalciumMask(:,:,:,SET(DATA.ViewPanels(panel)).CurrentSlice); + end + if ispapmusc + papimage = SET(no).PapillaryIM(:,:,:,SET(DATA.ViewPanels(panel)).CurrentSlice); + end + case {'montage','montagesegmented','montagerow'} + if strcmp(DATA.ViewPanelsType{panel},'montagesegmented')%and currentslice + slicestoinclude = segment('getmontagesegmentedslices',no); + [rows,cols] = calcfunctions('calcrowscols',no,length(slicestoinclude)); %.cols,.rows + else + slicestoinclude = 1:SET(no).ZSize; + [rows,cols] = calcfunctions('calcrowscols',no); %.cols,.rows + end + + %Set the correct number or rows and cols + + if strcmp(DATA.ViewPanelsType{panel},'montagerow') + n = rows*cols; + rows = min(rows,2); + cols = ceil(n/rows); + end + + matrix = [rows cols]; + + %Create space + im = zeros([SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) SET(no).TSize]); + if ispapmusc + papimage = false([SET(no).XSize*matrix(1) SET(no).YSize*matrix(2) SET(no).TSize]); + end + for tloop=1:SET(no).TSize + for i=1:numel(slicestoinclude) + zloop = slicestoinclude(i); + col = 1+mod(i-1,matrix(2)); + r = ceil(i/matrix(2)); + im(... + (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... + (1+(col-1)*SET(no).YSize):(col*SET(no).YSize),tloop) = ... + SET(no).IM(:,:,tloop,zloop); + if ispapmusc + papimage(... + (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... + (1+(col-1)*SET(no).YSize):(col*SET(no).YSize),tloop) = ... + SET(no).PapillaryIM(:,:,tloop,zloop); + end + end + end + case 'gla' + im = viewfunctions('getgla',no); + case 'vla' + im = permute(SET(no).IM(:,SET(no).VLA.slice,:,:),[4 1 3 2]); + case 'hla' + im = permute(SET(no).IM(SET(no).HLA.slice,:,:,:),[4 2 3 1]); +end + +if ispapmusc && ~isempty(papimage) + im(papimage) = DATA.GUISettings.PapilarColor; +end + +%do all resizing based on scale +if (scale==1) %exclude for 1, not sure if saves speed + outim = im; %Matlab performs copy by reference so should be fine with JIT +else + imxsz = size(im,1)*scale; + imysz = size(im,2)*scale; + outim = cast(zeros(imxsz,imysz,SET(no).TSize),'like',im); + + for t = 1:SET(no).TSize + outim(:,:,t) = imresize(im(:,:,t),[imxsz imysz],'bilinear'); + if ~isempty(calciumim) + calciumim(:,:,t) = imresize(im(:,:,t),[imxsz imysz],'nearest'); %#ok + end + end +end + +if calciumoverlay && ~isempty(calciumim) + im = calcfunctions('remapuint8viewim',outim,no); %Remap + rim = im; + gim = im; + bim = im; + + %colortable for the classes in calciummask + colortable = []; + colortable(1).class = uint8(1); %yellow + colortable(1).rgb = uint8([255 255 0]); + colortable(2).class = uint8(2); + colortable(2).rgb = uint8([0 255 255]); %cyan + colortable(3).class = uint8(3); + colortable(3).rgb = uint8([0 255 0]); %green + colortable(4).class = uint8(4); + colortable(4).rgb = uint8([255 255 255]); %white + colortable(5).class = uint8(5); + colortable(5).rgb = uint8([80 80 80]); %gray + colortable(6).class = uint8(6); + colortable(6).rgb = uint8([0 0 255]); %blue + colortable(7).class = uint8(7); + colortable(7).rgb = uint8([255 0 0]); %red + colortable(8).class = uint8(8); + colortable(8).rgb = uint8([204 0 204]); %lila + for loop = 1:length(colortable) + rim(calciumim==colortable(loop).class) = colortable(loop).rgb(1); + gim(calciumim==colortable(loop).class) = colortable(loop).rgb(2); + bim(calciumim==colortable(loop).class) = colortable(loop).rgb(3); + end + DATA.ViewIM{panel} = cat(5,rim,gim,bim); +else + %This is the default + DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',outim,no); +end + +%set zoom and aspectratio for axes + +viewfunctions('updatezoomandaspectratio',panel); +viewfunctions('updatetextposition',panel) +if panel==DATA.CurrentPanel + drawfunctions('drawselectedframe',panel) +end + diff --git a/source/createtree.m b/source/createtree.m index 2363424..bf9b2d7 100644 --- a/source/createtree.m +++ b/source/createtree.m @@ -1,77 +1,131 @@ -function [s,z,dirs] = createtree(pathname,s,z,dirs,ext) -%------------------------------------------------------- -%CREATETREE Finds all files in the input directory. +function [s,z,dirs] = createtree(pathname,ext) +%CREATETREE(PATHNAME,EXT) Finds all files in the input directory. % %Input: %- pathname %- extention (for instance '.mat' '.dcm'). Optional argument. - +% %Output: -%- cell array of full filenames to files -%- z size of the files. -%- dirs cell array of paths +%- s list of fullfilenames as cell array +%- z list of size of each file [OPTIONAL] +%- dirs list of folders [OPTIONAL] -%Creates a path tree (s), and sizes of files z +if nargin<2 + ext = []; +end -%Check for optional calling syntax +%Handle the case when called with empty extension +if isempty(ext) + ext = '*'; +else + ext = ['*',ext]; +end -if nargin<5 - if nargin<2 - ext = []; - else - ext = s; %Optional calling is createtree(pathname,ext) - end; -end; +%Extract the list using dir command +f = dir([pathname filesep '**' filesep ext]); %example f = dir('C:/DATA/**/*.dcm') returns dcm files -if nargin<3 +%Create full path. cat(1,{ffolder} converts to cell array and then use +%strcat to concatenate the strings +if isempty(f) s = {}; z = []; - dirs = {}; - levelone = true; -else - levelone = false; -end; + return +end -f=dir(pathname); +%remove directory pointers +f = f(~[f.isdir]); +if isempty(f) + s = {}; + z = []; + return +end + +s = strcat(cat(1,{f.folder}),repmat({filesep},1,length(f)),cat(1,{f.name})); -if levelone - h = waitbar(0,'Locating files.'); -end; +%Extract size +if nargout>1 + z = cat(1,f.bytes); +end -for loop = 1:length(f) - if f(loop).isdir - switch f(loop).name - case '.' - case '..' - otherwise - %disp(sprintf('Parsed Directory %s%s%s.',pathname,filesep,f(loop).name)) - [s,z,dirs] = createtree([pathname filesep f(loop).name],s,z,dirs,ext); - dirs = [dirs {[pathname filesep f(loop).name]}]; - end; - else - %disp(sprintf('add %s.',f(loop).name)); - if ~isempty(ext) - l = length(f(loop).name); - p = find(f(loop).name=='.'); - if (l>4) && (~isempty(p)) - if isequal(f(loop).name(p(end):l),ext) - s = [s {[pathname filesep f(loop).name]}]; - z = [z f(loop).bytes]; - end; - end; - else - %extenstion is empty => add allways - s = [s {[pathname filesep f(loop).name]}]; - z = [z f(loop).bytes]; - end; - end; - - if levelone - h = waitbar(loop/length(f),h);% Changed by Klas to waitbar instead of waitbarupdate. - end; -end; +%Extract list of folders +if nargout>2 + dirs = union(cat(1,{f.folder}),{}); %union sorts and removes duplicates +end -if levelone - close(h); -end; +%-----------OLD CODE --------------- +%function [s,z,dirs] = createtree(pathname,s,z,dirs,ext) +%CREATETREE Finds all files in the input directory. +% +%Input: +%- pathname +%- extention (for instance '.mat' '.dcm'). Optional argument. + +%Output: +%- cell array of full filenames to files +%- z size of the files. +%- dirs cell array of paths + +%Creates a path tree (s), and sizes of files z + +%Check for optional calling syntax +% if nargin<5 +% if nargin<2 +% ext = []; +% else +% ext = s; %Optional calling is createtree(pathname,ext) +% end +% end +% +% if nargin<3 +% s = {}; +% z = []; +% dirs = {}; +% levelone = true; +% else +% levelone = false; +% end +% +% f=dir(pathname); +% +% if levelone +% h = waitbar(0,'Locating files.'); +% end +% +% for loop = 1:length(f) +% if f(loop).isdir +% switch f(loop).name +% case '.' +% case '..' +% otherwise +% %disp(sprintf('Parsed Directory %s%s%s.',pathname,filesep,f(loop).name)) +% [s,z,dirs] = createtree([pathname filesep f(loop).name],s,z,dirs,ext); +% dirs = [dirs {[pathname filesep f(loop).name]}]; +% end +% else +% %disp(sprintf('add %s.',f(loop).name)); +% if ~isempty(ext) +% l = length(f(loop).name); +% p = find(f(loop).name=='.'); +% if (l>4) && (~isempty(p)) +% if isequal(f(loop).name(p(end):l),ext) +% s = [s {[pathname filesep f(loop).name]}]; +% z = [z f(loop).bytes]; +% end +% end +% else +% %extenstion is empty => add allways +% s = [s {[pathname filesep f(loop).name]}]; +% z = [z f(loop).bytes]; +% end +% end +% +% if levelone +% h = waitbar(loop/length(f),h);% Changed by Klas to waitbar instead of waitbarupdate. +% end +% end +% +% if levelone +% close(h); +% end +% diff --git a/source/croplvstacks.fig b/source/croplvstacks.fig index 26a3ad7..525761f 100644 Binary files a/source/croplvstacks.fig and b/source/croplvstacks.fig differ diff --git a/source/croplvstacks.m b/source/croplvstacks.m index b7f7f03..bb2f6f8 100644 --- a/source/croplvstacks.m +++ b/source/croplvstacks.m @@ -49,7 +49,7 @@ im = calcfunctions('remapuint8', ... SET(no).IM(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),no); imagesc(im,'Parent',gui.axh(i)); - colormap gray + colormap(gui.axh(i),'gray'); hold(gui.axh(i),'on'); set(gui.axh(i),'Visible','on'); axis(gui.axh(i),'image','off'); @@ -57,7 +57,7 @@ x = xall{i}; gui.frameh(i) = plot(gui.axh(i),[y(1) y(1) y(end) y(end) y(1)] , ... [x(1) x(end) x(end) x(1) x(1)],'y'); - gui.resizeh(i) = plot(gui.axh(i),y(end),x(end),'yd'); + gui.resizeh(i) = plot(gui.axh(i),y(end),x(end),'yo'); gui.translate(i) = plot(gui.axh(i),y(1),x(1),'yo'); set(gui.resizeh(i),'ButtonDownFcn',@(hObject,eventdata,handles)croplvstacks('resize',i)); set(gui.translate(i),'ButtonDownFcn',@(hObject,eventdata,handles)croplvstacks('move',i)); @@ -82,12 +82,16 @@ function cancel_Callback %#ok %-------------- global DATA -gui = DATA.GUI.CropLVStacks; -gui.state = false; -uiresume(gui.fig); + +try + gui = DATA.GUI.CropLVStacks; + gui.state = false; + uiresume(gui.fig); +catch +end %---------------- -function move(ix) +function move(ix) %#ok %---------------- global DATA gui = DATA.GUI.CropLVStacks; @@ -95,7 +99,7 @@ function move(ix) set(gui.fig,'WindowButtonUpFcn',@(hObject,eventdata,handles)croplvstacks('buttonup',ix)); %------------------ -function resize(ix) +function resize(ix) %#ok %------------------ global DATA gui = DATA.GUI.CropLVStacks; @@ -103,36 +107,50 @@ function resize(ix) set(gui.fig,'WindowButtonUpFcn',@(hObject,eventdata,handles)croplvstacks('buttonup',ix)); %---------------------- -function motion(arg,ix) +function motion(arg,ix) %#ok %---------------------- global DATA gui = DATA.GUI.CropLVStacks; [y,x] = mygetcurrentpoint(gui.axh(ix)); ax = axis(gui.axh(ix)); ax = ax + 0.5*[1 -1 1 -1]; - -xmin = gui.xall{ix}(1); -ymin = gui.yall{ix}(1); -xdiff = gui.xall{ix}(end)-xmin; -ydiff = gui.yall{ix}(end)-ymin; +% needed for the old proper move +% xmin = gui.xall{ix}(1); +% ymin = gui.yall{ix}(1); +% xdiff = gui.xall{ix}(end)-xmin; +% ydiff = gui.yall{ix}(end)-ymin; switch arg - case 'move' - y = round(min(max(y,ax(3)),ax(4)-ydiff)); - x = round(min(max(x,ax(1)),ax(2)-xdiff)); - set(gui.frameh(ix),'XData',[y y y+ydiff y+ydiff y], ... - 'YData',[x x+xdiff x+xdiff x x]); - set(gui.resizeh(ix),'XData',y+ydiff,'YData',x+xdiff); + %NOT moving but resizing from the left upper corner; + %needs renaming/refactoring in the future + case 'move' + xmax = gui.xall{ix}(end); + ymax = gui.yall{ix}(end); + y = round(max(1,min(ymax-2,y))); + x = round(max(1,min(xmax-2,x))); + set(gui.frameh(ix),'XData',[y y ymax ymax y], ... + 'YData',[x xmax xmax x x]); + set(gui.resizeh(ix),'XData',ymax,'YData',xmax); set(gui.translate(ix),'XData',y,'YData',x); + % old case with proper move +% case 'move' +% y = round(min(max(y,ax(3)),ax(4)-ydiff)); +% x = round(min(max(x,ax(1)),ax(2)-xdiff)); +% set(gui.frameh(ix),'XData',[y y y+ydiff y+ydiff y], ... +% 'YData',[x x+xdiff x+xdiff x x]); +% set(gui.resizeh(ix),'XData',y+ydiff,'YData',x+xdiff); +% set(gui.translate(ix),'XData',y,'YData',x); case 'resize' - y = round(min(max(y,ymin+1),ax(4))); - x = round(min(max(x,xmin+1),ax(2))); + xmin = gui.xall{ix}(1); + ymin = gui.yall{ix}(1); + y = round(max(ymin+2,min(ax(2),y))); + x = round(max(xmin+2,min(ax(4),x))); set(gui.frameh(ix),'XData',[ymin ymin y y ymin], ... 'YData',[xmin x x xmin xmin]); set(gui.resizeh(ix),'XData',y,'YData',x); set(gui.translate(ix),'XData',ymin,'YData',xmin); end %-------------------- -function buttonup(ix) +function buttonup(ix) %#ok %-------------------- global DATA gui = DATA.GUI.CropLVStacks; diff --git a/source/cropscreenshot.fig b/source/cropscreenshot.fig new file mode 100644 index 0000000..c773ac4 Binary files /dev/null and b/source/cropscreenshot.fig differ diff --git a/source/cropscreenshot.m b/source/cropscreenshot.m new file mode 100644 index 0000000..b4e6da9 --- /dev/null +++ b/source/cropscreenshot.m @@ -0,0 +1,426 @@ +function varargout = cropscreenshot(varargin) +% MATLAB code for cropscreenshot.fig +% disp(varargin{1}) +macro_helper(varargin{:}); +if nargin < 1 || isempty(varargin{1}) + varargin{1} = 'init'; +end + +[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard + +%------------ +function init %#ok +%------------ +%Initialize the GUI + +global DATA + +gui = mygui('cropscreenshot.fig'); +DATA.GUI.CropScreenshot = gui; +gui.handles.screenshotimgh = image([],'Parent',gui.handles.screenshotaxes); +axis(gui.handles.screenshotaxes,'image','off'); +gui.handles.screenshotaxes.Toolbar.Visible = 'off'; +gui.handles.cropbox = line(gui.handles.screenshotaxes,nan, nan,'Color','y','ButtonDownFcn', ... +'cropscreenshot(''cropbox_Buttondown'')', 'LineWidth', 0.75); +gui.handles.framebox = line(gui.handles.screenshotaxes,nan, nan,'Color','k','ButtonDownFcn', ... +'cropscreenshot(''cropbox_Buttondown'')', 'LineWidth', 2); +gui.handles.resizeu = line(gui.handles.screenshotaxes,nan, nan,'Color','y','LineStyle','None','Marker','o','ButtonDownFcn', ... +'cropscreenshot(''cropbox_Buttondown'')','LineWidth', 0.75); +gui.handles.resizel = line(gui.handles.screenshotaxes,nan, nan,'Color','y','LineStyle','None','Marker','o','ButtonDownFcn', ... +'cropscreenshot(''cropbox_Buttondown'')','LineWidth', 0.75); + +selectedbtn = gui.handles.selectcropregioncuibuttongroup.SelectedObject; +switch selectedbtn.Tag + case 'imagepanelradiobutton' + imagepanelradiobutton_Callback + case 'userselectionradiobutton' + setimage; + resetcropboundaries; + updatecropbox; +end + + +%------------------------------------- +function imagepanelradiobutton_Callback +%--------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; +setimage; +gui.handles.resetpushbutton.Enable = 'off'; + +%------------------------------------- +function userselectionradiobutton_Callback +%--------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; +try + gui.handles.resetpushbutton.Enable = 'on'; + setimage; + updatecropbox; +catch me + mydispexception(me) +end + +%------------------------------------- +function resetcropboundaries +%------------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; +[sizeX, sizeY,~] = size(gui.handles.screenshotimgh.CData); +gui.startx = 1; +gui.starty = 1; +gui.endx = sizeY; +gui.endy = sizeX; +%------------------------------------- +function resetframe +%------------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; +[sizeX, sizeY,~] = size(gui.handles.screenshotimgh.CData); +selectedbtn = gui.handles.selectcropregioncuibuttongroup.SelectedObject; +switch selectedbtn.Tag + case 'imagepanelradiobutton' + offset = 2; + case 'userselectionradiobutton' + offset = 5; +end + +startx = 1-offset; +starty = 1-offset; +endx = sizeY+offset; +endy = sizeX+offset; +boxX = [startx,endx,endx,startx,startx]; +boxY = [starty,starty,endy,endy,starty]; + +gui.handles.framebox.XData = boxX; +gui.handles.framebox.YData = boxY; + + +%------------------------------------- +function cropbox_Buttondown %#ok called as a string from init +%--------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; + +[y,x] = mygetcurrentpoint(gui.handles.screenshotaxes); + +%distance to startx/y +dstart = norm([gui.startx,gui.starty]-[y,x]); +dstop = norm([gui.endx,gui.endy]-[y,x]); + +if dstop <= 25 && dstop < dstart + %scale box lower point + pointtoscale = 'scalel'; +elseif dstart <= 25 + %scale box upper point + pointtoscale = 'scaleu'; +else + return +end + +gui.fig.WindowButtonMotionFcn = sprintf('cropscreenshot(''cropbox_Motion'',''%s'')',pointtoscale); +gui.fig.WindowButtonUpFcn = 'cropscreenshot(''cropbox_Buttonup'')'; + +%------------------------------------- +function cropbox_Motion(type) %#ok as string in cropbox_Buttondown +%--------------------------------- +%motion function to move cropping box points. +global DATA +gui = DATA.GUI.CropScreenshot; +[x,y] = mygetcurrentpoint(gui.handles.screenshotaxes); +[sizeX, sizeY,~] = size(gui.handles.screenshotimgh.CData); +switch type + case 'scaleu' + startx = min(sizeY,max(1,x)); + starty = min(sizeX,max(1,y)); + endx = gui.endx; + endy = gui.endy; + case 'scalel' + startx = gui.startx; + starty = gui.starty; + endx = min(sizeY,max(1,x)); + endy = min(sizeX,max(1,y)); +end + +%update params +gui.startx = startx; +gui.starty = starty; +gui.endx = endx; +gui.endy = endy; + +updatecropbox + +%------------------------------------- +function cropbox_Buttonup %#ok as string in cropbox_Buttondown +%--------------------------------- +%motion function for mid slice axes. Move box points. +global DATA +gui = DATA.GUI.CropScreenshot; +gui.fig.WindowButtonMotionFcn = ''; +gui.fig.WindowButtonUpFcn = ''; + +%------------------------------------- +function updatecropbox +%--------------------------------- +%updates cropbox +global DATA +gui = DATA.GUI.CropScreenshot; +boxX = [gui.startx,gui.endx,gui.endx,gui.startx,gui.startx]; +boxY = [gui.starty,gui.starty,gui.endy,gui.endy,gui.starty]; + +gui.handles.cropbox.XData = boxX; +gui.handles.cropbox.YData = boxY; + +gui.handles.resizeu.XData = gui.startx; +gui.handles.resizeu.YData = gui.starty; +gui.handles.resizel.XData = gui.endx; +gui.handles.resizel.YData = gui.endy; + +%------------------------------------- +function reset_Callback %#ok button callback +%--------------------------------- +resetcropboundaries; +userselectionradiobutton_Callback; + +%------------------------------------- +function close_Callback +%--------------------------------- +global DATA + +try + DATA.GUI.CropScreenshot = close(DATA.GUI.CropScreenshot); +catch me + mydispexception(me)%#ok + DATA.GUI.CropScreenshot =[]; + delete(gcbf); +end + +%------------------------------------- +function save_Callback %#ok called from gui +%--------------------------------- +[fname, extindex] = setfilename; +im = getimage; +successful = writeimage(im,fname,extindex); +if successful + close_Callback; +end + +%------------------------------------- +function [fname, extindex] = setfilename +%------------------------------------- +global DATA SET +gui = DATA.GUI.CropScreenshot; +selectedbtn = gui.handles.savefileuibuttongroup.SelectedObject; +switch selectedbtn.Tag + case 'fileradiobutton' + [filename, pathname,extindex] = myuiputfile(... + { '*.png','PNG image (*.png)';... + '*.jpg','JPEG image (*.jpg)';... + '*.bmp','BMP image (*.bmp)';... + '*.tif','TIFF image (*.tif)'},... + dprintf('Save file as'),'screenshot'); + case 'pacsradiobutton' + filename = char(myinputdlg({'Enter File Name'},'File name',1,{'screenshot'})); + isnotok = 1; + while isnotok + if isempty(filename) + return; + elseif ~isvarname(filename) + myfailed(dprintf('File name %s is not valid.\nFile name can contain letters, digits, and underscores',filename),DATA.GUI.Segment); + isnotok = 1; + filename = char(myinputdlg({'Enter File Name'},'File name',1,{'screenshot'})); + elseif isvarname(filename) + break; + end + end + pathname = getpreferencespath; + extindex = 5; + case 'reportradiobutton' + name = removeforbiddenchars(SET(1).PatientInfo.Name); + if isempty(name) + name = 'Hidden'; + end + pathname = fullfile(DATA.Pref.Pacs.ReportsheetPath, ... + name,'Screenshots'); + if ~exist(pathname,'dir') + sucess = mkdir(pathname); + if ~sucess + myfailed('Could not create screenshot directory. Aborted'); + return + end + end + reportdir = dir(fullfile(pathname,'screenshot*.png')); + nbrs = zeros(1,numel(reportdir)); + for i = 1:numel(reportdir) + nbrs(i) = sscanf(reportdir(i).name(12:15),'%f'); + end + newnbr = min(setdiff(1:9999,nbrs)); + filename = sprintf('screenshot_%04.0f.png',newnbr); + extindex = 1; + if ~isfield(DATA.Pref.Pacs, 'ScreenshotPath') + DATA.Pref.Pacs.ScreenshotPath = pathname; + elseif ~strcmp(DATA.Pref.Pacs.ScreenshotPath, pathname) + DATA.Pref.Pacs.ScreenshotPath = pathname; + end + case 0 + filename = 0; +end + +fname = fullfile(pathname,filename); +%Add extension if necessary +[~,~,ext] = fileparts(fname); +if isempty(ext) + switch extindex + case 1 + fname = [fname '.png']; + case 2 + fname = [fname '.jpg']; + case 3 + fname = [fname '.bmp']; + case 4 + fname = [fname '.tif']; + case 5 + fname = [fname '.dcm']; + end +end + +%------------------------------------- +function successful = writeimage(im,fname,extindex) +%------------------------------------- +global DATA +successful = false; +switch extindex + case 1 + try + imwrite(im,fname,'png','bitdepth',8,'software','Segment',... + 'creationtime',datestr(now)); + disp('Export successful'); + successful = true; + catch me + mydispexception(me); + disp('Export failed'); + end + case 2 + try + imwrite(im,fname,'jpg','quality',100); + disp('Export successful'); + successful = true; + catch me + mydispexception(me); + disp('Export failed'); + end + case 3 + try + imwrite(im,fname,'bmp'); + successful = true; + disp('Export successful'); + catch me + mydispexception(me) + disp('Export failed'); + end + case 4 + try + imwrite(im,fname,'tif'); + successful = true; + disp('Export successful'); + catch me + mydispexception(me); + disp('Export failed'); + end + + case 5 + makeimagedicom(im,fname,DATA.ViewPanels(DATA.CurrentPanel)); + try + successful = pacsaccess('savetopacs_helper',{fname},getpreferencespath); + catch me + successful = 0; + mydispexception(me); + myfailed(me.message); + end + try + status = 1; + delete(fname) + catch me + mydispexception(me) + status = 0; + end + + if successful + stri = dprintf('Save to PACS success'); + else + stri = dprintf('Save to PACS failed'); + end + + if status == 1 + stri = [stri,dprintf(', succesfully removed report from computer.')]; + else + stri = [stri,dprintf(', failed to remove report from computer.')]; + end + mymsgbox(stri) +end + +%--------------------------------- +function img = getimage +%--------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; +img = []; +selectedbtn = gui.handles.selectcropregioncuibuttongroup.SelectedObject; +switch selectedbtn.Tag + case 'imagepanelradiobutton' + try + img = gui.handles.screenshotimgh.CData; + catch me + mydispexception(me); + end + case 'userselectionradiobutton' + [sizeX, sizeY,~] = size(gui.handles.screenshotimgh.CData); + gui.startx = min(sizeY,max(1,round(gui.startx))); + gui.starty = min(sizeX,max(1,round(gui.starty))); + gui.endx = min(sizeY,max(1,round(gui.endx))); + gui.endy = min(sizeX,max(1,round(gui.endy))); + try + img = gui.handles.screenshotimgh.CData(gui.starty:gui.endy,gui.startx:gui.endx,:); + catch me + mydispexception(me); + end +end + +%--------------------------------- +function setimage +%--------------------------------- +global DATA +gui = DATA.GUI.CropScreenshot; +selectedbtn = gui.handles.selectcropregioncuibuttongroup.SelectedObject; +try + switch selectedbtn.Tag + case 'imagepanelradiobutton' + h = DATA.Handles.boxaxes; + imgframe = mygetframe(h); + boxvis = 'off'; + case 'userselectionradiobutton' + % get whole figure of segment as a frame + sgui = DATA.GUI.Segment; + imgframe = mygetframe(sgui.fig); + imgframe.colormap = colormap(sgui.fig); + boxvis = 'on'; + end + img = frame2im(imgframe); + gui.handles.screenshotimgh.CData = img; + set([gui.handles.cropbox,gui.handles.resizeu,gui.handles.resizel],'Visible',boxvis); + resetframe; +catch me + mydispexception(me); +end + + + + + + + + + + + + diff --git a/source/cutgui.fig b/source/cutgui.fig deleted file mode 100644 index dae48ba..0000000 Binary files a/source/cutgui.fig and /dev/null differ diff --git a/source/cutgui.m b/source/cutgui.m index 124e7bc..7817164 100644 --- a/source/cutgui.m +++ b/source/cutgui.m @@ -3,7 +3,7 @@ if nargin==0 varargin = {'init'}; -end; +end macro_helper(varargin{:}); [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard diff --git a/source/cxt1map2segment.m b/source/cxt1map2segment.m index ae5a129..5d5c20b 100644 --- a/source/cxt1map2segment.m +++ b/source/cxt1map2segment.m @@ -65,9 +65,8 @@ function cxt1map2segment() end calcpreview = true; -segment('makeviewim',DATA.CurrentPanel,NO); -segment('updatemodeldisplay'); -drawfunctions('drawimageno'); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawno',NO) drawfunctions('drawthumbnails',calcpreview); end end \ No newline at end of file diff --git a/source/dcmconv.exe b/source/dcmconv.exe index 85eda4a..18a8b14 100644 Binary files a/source/dcmconv.exe and b/source/dcmconv.exe differ diff --git a/source/dcmdata.dll b/source/dcmdata.dll new file mode 100644 index 0000000..cc876ee Binary files /dev/null and b/source/dcmdata.dll differ diff --git a/source/dcmdjpeg.exe b/source/dcmdjpeg.exe index 5e5bb63..0977e88 100644 Binary files a/source/dcmdjpeg.exe and b/source/dcmdjpeg.exe differ diff --git a/source/dcmimgle.dll b/source/dcmimgle.dll new file mode 100644 index 0000000..21fdb09 Binary files /dev/null and b/source/dcmimgle.dll differ diff --git a/source/dcmjpeg.dll b/source/dcmjpeg.dll new file mode 100644 index 0000000..002b4d1 Binary files /dev/null and b/source/dcmjpeg.dll differ diff --git a/source/dcmnet.dll b/source/dcmnet.dll new file mode 100644 index 0000000..1172227 Binary files /dev/null and b/source/dcmnet.dll differ diff --git a/source/dcmodify.exe b/source/dcmodify.exe index e7dbff9..4946713 100644 Binary files a/source/dcmodify.exe and b/source/dcmodify.exe differ diff --git a/source/dcmtls.dll b/source/dcmtls.dll new file mode 100644 index 0000000..8f4a9a7 Binary files /dev/null and b/source/dcmtls.dll differ diff --git a/source/deformit_new.mexw32 b/source/deformit_new.mexw32 deleted file mode 100644 index dff5dcc..0000000 Binary files a/source/deformit_new.mexw32 and /dev/null differ diff --git a/source/deformit_newlv.mexw32 b/source/deformit_newlv.mexw32 deleted file mode 100644 index b900f3f..0000000 Binary files a/source/deformit_newlv.mexw32 and /dev/null differ diff --git a/source/dialogiconsblack.mat b/source/dialogiconsblack.mat new file mode 100644 index 0000000..076c7a1 Binary files /dev/null and b/source/dialogiconsblack.mat differ diff --git a/source/dialogiconsblue.mat b/source/dialogiconsblue.mat new file mode 100644 index 0000000..39b31be Binary files /dev/null and b/source/dialogiconsblue.mat differ diff --git a/source/dicomanonymize.p b/source/dicomanonymize.p index 7044232..66383d8 100644 Binary files a/source/dicomanonymize.p and b/source/dicomanonymize.p differ diff --git a/source/dicomconvert.m b/source/dicomconvert.m index 9d16637..df42264 100644 --- a/source/dicomconvert.m +++ b/source/dicomconvert.m @@ -2,10 +2,10 @@ function dicomconvert(infile,outfile,dinfo) %DICOMCONVERT(INFILE,OUTFILE,[SYNTAX]); % %Reads the infile and writes the outfile with a new transfersyntax (default -%is 1.2.840.10008.1.2.1 (Explicit VT little endian). If transfer syntax is specified then Matlab -%routines aree used, otherwise DCMTK routines are used (which is much faster). -% -%If called with only one file, then convert filename with the same +%is 1.2.840.10008.1.2.1 (Explicit VT little endian). If transfer syntax is specified then Matlab +%routines aree used, otherwise DCMTK routines are used (which is much faster). +% +%If called with only one file, then convert filename with the same %outfilename. %Einar Heiberg @@ -14,13 +14,27 @@ function dicomconvert(infile,outfile,dinfo) usedcmtk = true; %true for a start +jpeglist=[{'1.2.840.10008.1.2.4.57'};... +{'1.2.840.10008.1.2.4.70'};... +{'1.2.840.10008.1.2.4.90'};... +{'1.2.840.10008.1.2.4.50'};... +{'1.2.840.10008.1.2.4.51'};... +{'1.2.840.10008.1.2.4.70'};... +{'1.2.840.10008.1.2.4.80'};... +{'1.2.840.10008.1.2.4.81'};... +{'1.2.840.10008.1.2.4.91'};... +{'1.2.840.10008.1.2.4.91'};... +{'1.2.840.10008.1.2.4.92'}]; + +warnId=[]; %#ok + if nargin<2 outfile = infile; -end; +end if ~exist(infile,'file') error('Input file does not exist.'); -end; +end if nargin<3 try @@ -29,35 +43,46 @@ function dicomconvert(infile,outfile,dinfo) try dinfo = dicominfo(infile); catch me - error(sprintf('Could not read DICOM file %s.',infile)); %#ok - mydispexception(me); + mydispexception(me); + error('Could not read DICOM file %s.',infile); end - end; -end; + end +end -if isequal(dinfo.TransferSyntaxUID,'jpeg') || isequal(dinfo.TransferSyntaxUID,'1.2.840.10008.1.2.4.90') - usedcmtk = false; +%if isequal(dinfo.TransferSyntaxUID,'jpeg') || isequal(dinfo.TransferSyntaxUID,'1.2.840.10008.1.2.4.90')|| isequal(dinfo.TransferSyntaxUID,'1.2.840.10008.1.2.4.70') +if isequal(dinfo.TransferSyntaxUID,'jpeg') || any(ismember(dinfo.TransferSyntaxUID,jpeglist)) + usedcmtk = false; elseif isequal(dinfo.TransferSyntaxUID,'explicitbigendian') || isequal(dinfo.TransferSyntaxUID,'1.2.840.10008.1.2.2') usedcmtk = true; -end; - - +end if usedcmtk stri = sprintf('dcmconv%s +te "%s" "%s"',myexecutableext,infile,outfile); %+te write explicit VR little endian. [s,w] = system(stri); if ~isequal(s,0) error(w); - end; -else + end +else %Read the image try + lastwarn(''); % Clear last warning message + dinfo = dicominfo(infile); %re-read dinfo with stable loader to get all correctly read. + + [msg, warnId] = lastwarn; %Check the warning status + if ~isempty(warnId) + warning('off',warnId); + try + deletedicomtag('2001,105f',infile) %Special fix to dr Paul Joy dataset; Philips JPEG + catch + sprintf('Unable to delete ''2001,105f'' tag. There might be another tag to remove : %s',msg) + end + end X = dicomread(dinfo); catch me mydispexception(me); - error(sprintf('Could not read DICOM image in file %s',infile)); %#ok - end; + error('Could not read DICOM image in file %s',infile); + end %Display information if isequal(infile,outfile) @@ -65,7 +90,7 @@ function dicomconvert(infile,outfile,dinfo) else disp(sprintf('Converted encoding in files %s => %s.',infile,outfile)); %#ok end - + %Set new transfersyntax dinfo.TransferSyntaxUID = outsyntax; @@ -75,9 +100,19 @@ function dicomconvert(infile,outfile,dinfo) dicomwrite(X,outfile,dinfo); catch me mydispexception(me); - error(sprintf('Could not write DICOM file to %s',outfile)); %#ok - end; -end; - + error('Could not write DICOM file to %s',outfile); + end +end +%----------------------------------------------------------------------------------------------------------- +function deletedicomtag(tag, file) +%----------------------------------------------------------------------------------------------------------- +%Function to delete tag from dicom file +global DATA +source=[DATA.SegmentFolder filesep 'dcmodify']; +stri = sprintf('"%s" -nb -e (%s) "%s"', source, tag, file); +[status,~] = system(stri); +if ~isequal(status,0) + fprintf('Warning, error in deleting tag (%s) in %s.\n',tag, file); +end \ No newline at end of file diff --git a/source/dicomsorter.p b/source/dicomsorter.p index 09a9e45..46a9a2f 100644 Binary files a/source/dicomsorter.p and b/source/dicomsorter.p differ diff --git a/source/dijkstra.mexw32 b/source/dijkstra.mexw32 deleted file mode 100644 index 8600e71..0000000 Binary files a/source/dijkstra.mexw32 and /dev/null differ diff --git a/source/dinfo.fig b/source/dinfo.fig index 54cedb6..fa7a336 100644 Binary files a/source/dinfo.fig and b/source/dinfo.fig differ diff --git a/source/domatfiles.m b/source/domatfiles.m deleted file mode 100644 index 0a290ca..0000000 --- a/source/domatfiles.m +++ /dev/null @@ -1,81 +0,0 @@ -% DOMATFILES Script that opens Segment Makematlab to load DICOM files and save -% them to a .mat file - -% Parse inputfile to get list of DICOMs -readok = true; -failmsg = ''; -try - fid = fopen('domatfilesinput.txt','r'); - if fid<0 - readok = false; - failmsg = 'Could not open input file'; - else - outputpath = fgetl(fid); - transferid = fgetl(fid); - nbrofseries = str2double(fgetl(fid)); - dicomcell = cell(nbrofseries,1); - for i = 1:nbrofseries - nbroffiles = str2double(fgetl(fid)); - subcell = cell(nbroffiles,1); - for j = 1:nbroffiles - subcell{j} = fgetl(fid); - end - dicomcell{i} = subcell; - end - end; -catch me - readok = false; - failmsg = 'Could not read input file'; -end -try - fclose(fid); -catch me - readok = false; - failmsg = 'Could close input file'; -end; - -% Load files in Segment CMR and save to a .mat file -global DATA SET -if readok - try - transfer.domatfilesgo; %Start Segment Makematlab - DATA.GUISettings.AskToExitProgram = false; - DATA.Pref.DoNotAsk = true; - - %Loop over stacks to load - for i = 1:nbrofseries - if ~isempty(dicomcell{i}) - openfile('loadfiles',dicomcell{i},false,[]); - end - end - DATA.Silent = true; - - %autocropall; %Automatically crop it - - [pathname,filename] = fileparts(outputpath); - [SET.transferid] = deal(transferid); %Update transfer information = ID stamp the source - - %Store it - fail = filemenu('saveallas_helper',pathname,filename,false); - if fail - error('SEGMENT:ERROR','Could not save .mat file'); - end - catch me - mydispexception(me); - failmsg = me.message; - s = regexp(failmsg,'\n'); - for j = s - failmsg(j) = ' '; - end - end - filemenu('quit_Callback'); -end - -fid = fopen('domatfilesoutput.txt','w'); -if isempty(failmsg) - fprintf(fid,'SUCCESS\n'); -else - fprintf(fid,'FAILED\n'); - fprintf(fid,failmsg); -end -fclose(fid); \ No newline at end of file diff --git a/source/drawfunctions.m b/source/drawfunctions.m index 28afc27..c695cb5 100644 --- a/source/drawfunctions.m +++ b/source/drawfunctions.m @@ -1,5891 +1,1939 @@ - function drawfunctions(varargin) -% DRAWFUNCTIONS -% Functions for drawing image panels, slices and montages -% -% Moved out from segment_main by Nisse Lundahl +function [varargout] = drawfunctions(varargin) +% Functions for drawing in panels +% Klas %Invoke subfunction macro_helper(varargin{:}); %future macro recording use -feval(varargin{:}); % FEVAL switchyard +if (nargout) + [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard +else + feval(varargin{:}); % FEVAL switchyard +end -%---------------------------------------- -function drawimageview(nos,sz,panelstype) -%---------------------------------------- -%Draws a full view specified by the arguments -global DATA NO +%----------------------- +function drawthumbnails(calculatepreview,sliderupdated) %#ok +%----------------------- +%Draw all thumbnails. Calculatepreview is a boolean +%indicating if thumbnails needs to be redrawn. -if nargin < 3 - panelstype = cell(sz); - [panelstype{:}] = deal('one'); -end +global DATA SET +persistent setlength -if isempty(nos) - nos = NO; -else - if DATA.CurrentPanel > numel(nos) || nos(DATA.CurrentPanel) ~= NO - DATA.CurrentPanel = find(nos==NO,1,'last'); - if isempty(DATA.CurrentPanel) - DATA.CurrentPanel = find(nos,1,'last'); - NO = nos(DATA.CurrentPanel); - end - end +if DATA.Silent || (~DATA.DataLoaded) || isempty(DATA.Handles.datasetaxes) + return; end -DATA.ViewPanelsType = panelstype; -for i = 1:numel(nos) - if nos(i) > 0 && ismember(panelstype{i},{'montage'}) - [rows,cols] = calcfunctions('calcrowscols',nos(i)); - DATA.ViewPanelsMatrix{i} = [rows cols]; - else - DATA.ViewPanelsMatrix{i} = []; - end +if isempty(DATA.VisibleThumbnails) + DATA.VisibleThumbnails=1:min(DATA.Pref.NumberVisibleThumbnails,length(SET)); + setlength=length(SET); end -DATA.ViewPanels = nos; -DATA.ViewIM = cell(1,numel(nos)); - -drawall(sz(1),sz(2)); -%-------------------- -function drawall(n,m) -%-------------------- -%Draws all panels that should be visible or up to the number specified as n. -% If called with n=[], then lookup from imagepanels -% When n,m specified draw n*m panels. +thumbsize=DATA.GUISettings.ThumbnailSize; +if nargin<2 ||(nargin==2 && not(sliderupdated)) + segment('updateslider'); +end -global DATA SET NO +if nargin<1 + calculatepreview=0; +end -gotrowscols = false; +if setlength~=length(SET) + calculatepreview=1; +end +setlength=length(SET); -if DATA.Silent - return; -end; - -%this is a bit cryptic------------- Klas -if nargin==0 - pos = find(DATA.ViewPanels==0); - if isempty(pos) - n = length(DATA.ViewPanels); - else - n = pos(1)-1; - end; -end; +if calculatepreview + delete(DATA.Handles.datasetaxes.Children) + calcfunctions('calcdatasetpreview'); +end +DATA.Handles.datasetpreviewimage = image(DATA.DATASETPREVIEW,'parent',DATA.Handles.datasetaxes); +set(DATA.Handles.datasetpreviewimage,'ButtondownFcn',... + sprintf('%s(''thumbnail_Buttondown'')','segment')); +%colormap(DATA.Colormap); %no longer needed, now truecolor /JU +axis(DATA.Handles.datasetaxes,'image','off','ij'); +% axis(DATA.Handles.datasetaxes,) +ylim=[(DATA.VisibleThumbnails(1)-1) DATA.VisibleThumbnails(end)]*thumbsize+1; +set(DATA.Handles.datasetaxes,'ylim',ylim ,'dataaspectratio', [1 1 1]); +hold(DATA.Handles.datasetaxes,'on'); -if isempty(n) - n = length(DATA.ViewPanels); -end; +%draw frames +drawthumbnailframes; +%print number of thumbnail in the upper left corner of the image +DATA.printthumbnailnumber(thumbsize); -if length(n)>1 - temp = n; - n = n(1); - m = temp(2); - n = n*m; %see below - gotrowscols = true; -end; +hold(DATA.Handles.datasetaxes,'off'); -%If called by two input arguments then it is row*cols -if nargin==2 - n = n*m; - gotrowscols = true; -end; +%--------------------------- +function drawthumbnailframes +%--------------------------- +%Draw frames around thumbnail images +global DATA SET NO -%------------------------------------------ +if isempty(DATA.Handles.datasetaxes) + return +end -%Delete the old ones first +thumbsize=DATA.GUISettings.ThumbnailSize; try - delete(DATA.Handles.imageaxes); - delete(DATA.Handles.boxaxes); + delete(DATA.Handles.datasetpreviewline); + delete(DATA.Handles.datasetflowline); catch %#ok -end; - -%--- Find out configuration -if ~gotrowscols - switch n - case {0,1} - rows = 1; - cols = 1; - case 2 - rows = 1; - cols = 2; - case 3 - rows = 3; - cols = 1; - case 4 - rows = 2; - cols = 2; - case {5,6} - rows = 2; - cols = 3; - case {7,8} - rows = 2; - cols = 4; - case 9 - rows = 3; - cols = 3; - case {10,11,12} - rows = 3; - cols = 4; - case {13,14,15} - rows = 3; - cols = 5; - case 16 - rows = 4; - cols = 4; - case {17,18} - rows = 3; - cols = 6; - case {19,20} - rows = 4; - cols = 5; - case 21 - rows = 3; - cols = 7; - case {22,23,24} - rows = 4; - cols = 6; - otherwise - cols = ceil(sqrt(n)); - rows = ceil(n/cols); - end; -else - %Two input arguments - rows = n/m; %see above, nargin==2 clause before. - cols = m; -end; - -% if strcmp(DATA.ViewPanelsType{1},'ortho') -% panelstype = cell(1,n); -% panelstype{1}='one'; -% sz = [rows,cols]; -% nos = DATA.ViewPanels(1); -% drawimageview(nos,sz,panelstype) -% return -% end - -if length(DATA.ViewPanels) 1 + linkies = SET(NO).Linked(SET(NO).Linked ~= NO); + ind = ismember(visibleandlinked,linkies); + set(DATA.Handles.datasetflowline(ind),'visible','on'); end -%Store for future use. -DATA.ViewMatrix = [rows cols]; - -%--- Add new axes - -left = DATA.GUISettings.LeftGapWidth; %0.12; -right = 1-DATA.GUISettings.RightGapWidth-0.02; %Based on that the report panel can never be more than 220. -bottom = DATA.GUISettings.BottomGapHeight; %0.013; -top = 1-DATA.GUISettings.TopGapHeight; -width = right-left; -height = top-bottom; - -%Create image area with grid for boxes. -DATA.Handles.boxaxes = axes('position',... - [left bottom width height],... - 'parent',DATA.imagefig,'visible','off'); - -%2 => 0.5 -%3 => 0.333 0.666 -h = []; -hold(DATA.Handles.boxaxes,'on'); -for rloop=1:(rows-1) - h = [h;plot(DATA.Handles.boxaxes,[0 1],[1/rows*rloop 1/rows*rloop],DATA.GUISettings.BoxAxesLineSpec)]; %#ok -end; -for cloop=1:(cols-1) - h = [h;plot(DATA.Handles.boxaxes,[1/cols*cloop 1/cols*cloop],[0 1],DATA.GUISettings.BoxAxesLineSpec)]; %#ok -end; -h = [h;plot(DATA.Handles.boxaxes,[0 1],[0 0],DATA.GUISettings.BoxAxesLineSpec)]; -h = [h;plot(DATA.Handles.boxaxes,[0 1],[1 1],DATA.GUISettings.BoxAxesLineSpec)]; -h = [h;plot(DATA.Handles.boxaxes,[0 0],[0 1],DATA.GUISettings.BoxAxesLineSpec)]; -h = [h;plot(DATA.Handles.boxaxes,[1 1],[0 1],DATA.GUISettings.BoxAxesLineSpec)]; -hold(DATA.Handles.boxaxes,'off'); -axis(DATA.Handles.boxaxes,'off'); -set(h,'color',DATA.GUISettings.BoxAxesColor,'linewidth',2); - -h = []; -for rloop=(rows-1):-1:0; - for cloop=0:(cols-1); - h = [h axes('position',... - [left+cloop*width/cols bottom+rloop*height/rows width/cols height/rows],... - 'parent',DATA.imagefig,'visible','off')]; %#ok - end; -end; - -%Store handles -DATA.Handles.imageaxes = h; - -totn = cols*rows; - -%--- Hide all images -set(DATA.Handles.imageaxes,... - 'visible','off',... - 'xtick',[],'ytick',[]); - -%---Add to list of what panels contains what -if (n==1) - if ~isempty(DATA.ViewPanels) - %If one the display current - DATA.ViewPanels = DATA.ViewPanels(DATA.CurrentPanel); - DATA.ViewPanelsType = DATA.ViewPanelsType(DATA.CurrentPanel); - DATA.ViewPanelsMatrix = DATA.ViewPanelsMatrix(DATA.CurrentPanel); - DATA.ViewIM = DATA.ViewIM(DATA.CurrentPanel); - if ismember(DATA.ViewPanelsType{1},{'ortho','hla','vla','gla'}); - if ~strcmp(DATA.ViewPanelsType{1},'ortho') - DATA.ViewIM{1} = []; - end - DATA.ViewPanelsType{1} = 'one'; - end - if numel(DATA.Overlay) >= DATA.CurrentPanel - DATA.Overlay = DATA.Overlay(DATA.CurrentPanel); - end - DATA.CurrentPanel = 1; - else - DATA.ViewPanels = []; - DATA.ViewPanelsType = {}; - DATA.ViewPanelsMatrix = {}; - DATA.ViewIM = {}; - DATA.Overlay = []; - segment('addtopanels',1); - end; -else - if length(DATA.ViewPanels)>totn - DATA.ViewPanels = DATA.ViewPanels(1:totn); %remove - DATA.ViewPanelsType = DATA.ViewPanelsType(1:totn); %remove - DATA.ViewPanelsMatrix = DATA.ViewPanelsMatrix(1:totn); %remove - DATA.ViewIM = DATA.ViewIM(1:totn); %remove - if totn < 4 - [DATA.ViewIM{ismember(DATA.ViewPanelsType, ... - {'hla','vla','gla'})}] = deal([]); - [DATA.ViewPanelsType{ismember(DATA.ViewPanelsType, ... - {'ortho','hla','vla','gla'})}] = deal('one'); - end - if not(isempty(DATA.Overlay)) - DATA.Overlay = DATA.Overlay(1:totn); - end - else - if length(DATA.ViewPanels)0); - -if (length(panelstodo)==1)&&(isequal(DATA.ViewPanelsType{1},'mmodespatial')) - DATA.ViewPanelsType{1} = 'one'; -end; - -%Weird but necessary switcheroo. -temppanel=min(DATA.CurrentPanel,length(DATA.ViewPanels)); -temppanel2=DATA.CurrentPanel; -DATA.CurrentPanel=temppanel; - -for panel=panelstodo; - no = DATA.ViewPanels(panel); - drawimagepanel(panel); - showedits(no); - %adding XYZ coordinates to 3DPtab images - if isequal(DATA.CurrentTheme,'3dp')&& length(panelstodo) == 4 ||... - isequal(DATA.CurrentTheme,'3dp')&& length(panelstodo) == 2 - if panel ~= 2 - drawimagetypetext3dp(NO,panel) - updatevisibility - end - end -end; +%draw frame around current image +ypos = (NO-1)*thumbsize+1; +DATA.Handles.datasetpreviewline = plot(DATA.Handles.datasetaxes,... + [1 1 thumbsize thumbsize 1 ],... + [ypos ypos+thumbsize-1 ypos+thumbsize-1 ypos ypos],... + 'color',DATA.GUISettings.ThumbLineColor); + +%--------------------- +function killhandles %#ok +%----------------------- +global DATA -segment('switchtopanel',temppanel2,1); +if ~isfield(DATA.Handles,'imageaxes') + return +end -segment('updateselectedslices'); +graphics = []; +for i = 1:length(DATA.Handles.imageaxes) + graphics = [graphics;DATA.Handles.imageaxes(i).Children]; +end -%Draw intersections -drawintersections; +delete(graphics) +delete(DATA.Handles.boxaxes) +delete(DATA.Handles.imageaxes) +%--------------------- +function setxynan(panels)%#ok +%----------------------- +%this function hides all overlay and axes by nan setting all objects. +global DATA -%Update title on window -DATA.updatetitle; +%all imageaxes needs to be checked. +if nargin == 0 + panels = 1:length(DATA.Handles.imageaxes); +end -%Update theme -updatetool; +%If a panel contains any image information then it needs to be cleared as +%it is likely that there should be a new stack in that panel after the +%configuration of the panels. +graphics = []; +for i = panels + if ~isempty(DATA.Handles.imagehandles(i).CData) + graphics = [graphics;DATA.Handles.imageaxes(i).Children]; %#ok + end +end -%Render iconplaceholders aswell -DATA.Handles.toggleiconholder.render -DATA.Handles.permanenticonholder.render -if ~isempty(DATA.Handles.configiconholder.cdata) - DATA.Handles.configiconholder.render +%nan set all objects in panel image is always last so fish by setting it as +%empty +for i = 1:length(graphics) + if strcmp(graphics(i).Type,'contour') + %This is the contour case + %tmp = [1,0;0,0]; + %set(graphics(i),'ZData',tmp,'XData',tmp,'YData',tmp); + %graphics(i).Visible = 'off'; %This is needed in 3DPrint due to Matlab bug + + graphics(i).ZData = [1,0;0,0]; + graphics(i).Visible = 'off'; %This is needed in 3DPrint due to Matlab bug + + elseif strcmp(graphics(i).Type,'image') + graphics(i).CData = []; + elseif isprop(graphics(i),'XData') + graphics(i).XData = nan; + graphics(i).YData = nan; + elseif isprop(graphics(i),'Position') + graphics(i).Position = [nan nan]; + end end + +%--------------------- +function drawtext(panel) %#ok +%----------------------- +%drawtext -%Make now one orange -set(DATA.Handles.imageaxes,... - 'xcolor',[0 0 0],'ycolor',[0 0 0]); -set(DATA.Handles.imageaxes(DATA.CurrentPanel),... - 'xcolor',DATA.GUISettings.AxesColor,'ycolor',DATA.GUISettings.AxesColor,'linewidth',2.5); +global DATA SET - -%---------------------- START3DDRAWFUNCTIONS ---------------------------- +if isempty(panel) + return +end -%-------------------------------- - function displaypoints(view,ima) -%-------------------------------- -%Draws annotation points in 3dp imageaxes ima according to view. +no = DATA.ViewPanels(panel); +slice = []; +switch DATA.ViewPanelsType{panel} + case 'trans3DP' + slice = SET(no).LevelSet.View.RSlice; + case 'sag3DP' + slice = SET(no).LevelSet.View.GSlice; + case 'cor3DP' + slice = SET(no).LevelSet.View.BSlice; + case {'one','montage','montagerow'} + slice = SET(no).CurrentSlice; +end -global SET DATA NO +%we do not need to do the full update here it is sufficient if we update +%the current image and corresponding lines in the others -%add points -[r,g,b] = segment3dp.tools('xyz2rgb',SET(NO).Point.X,SET(NO).Point.Y, SET(NO).Point.Z); -switch view - case 'r' - pointstoplot = round(r)==SET(NO).LevelSet.View.RSlice; - x=g; - y=b; - case 'g' - pointstoplot = round(g)==SET(NO).LevelSet.View.GSlice; - x=b; - y=r; - case 'b' - pointstoplot = round(b)==SET(NO).LevelSet.View.BSlice; - x=g; - y=r; +stri = ''; +if ~isempty(SET(DATA.ViewPanels(panel)).DICOMImageType) + stri = sprintf('%s\n',SET(DATA.ViewPanels(panel)).DICOMImageType); end -delete(DATA.Handles.([view,'text3dp']))%This removes old points -DATA.Handles.([view,'text3dp']) = []; - -if any(pointstoplot) - for loop = find(pointstoplot) - DATA.Handles.([view,'text3dp'])=[DATA.Handles.([view,'text3dp']),text('parent',ima,... - 'position',[x(loop) y(loop)],'HorizontalAlignment','center',... - 'string','+','color',[1,1,1]), text('parent',ima,... - 'position',[x(loop)+5 y(loop)],'HorizontalAlignment','left',... - 'string',SET(NO).Point.Label{loop},'color',[1,1,1])]; - set(DATA.Handles.([view,'text3dp']),'ButtonDownFcn','segment3dp.tools(''delete3dppoints'')'); - end +if ~isempty(SET(DATA.ViewPanels(panel)).SeriesDescription) + stri = [stri sprintf('%s\n',SET(DATA.ViewPanels(panel)).SeriesDescription)]; end +if ~isnan(SET(DATA.ViewPanels(panel)).TimeVector(SET(DATA.ViewPanels(panel)).CurrentTimeFrame)) + stri = [stri dprintf('Time: %.0f ms\n',1000*SET(DATA.ViewPanels(panel)).TimeVector(SET(DATA.ViewPanels(panel)).CurrentTimeFrame))]; +end +if (SET(DATA.ViewPanels(panel)).ZSize>1) && ~isempty(slice) + stri = [stri dprintf('Slice: %d',slice)]; +end -%---------------- -function rupdate -%---------------- -%Update 'red' image +DATA.Handles.text(panel).String = stri; -global DATA SET NO +%--------------------- +function drawmeasures(panel) %#ok +%----------------------- +global DATA SET -handles = DATA.Handles; -imh=handles.imagehandle(strcmp(DATA.ViewPanelsType,'trans3DP')); -ima=handles.imageaxes(strcmp(DATA.ViewPanelsType,'trans3DP')); +no = DATA.ViewPanels(panel); -if isempty(ima) - return +scale = viewfunctions('getscale',panel); +slices = viewfunctions('slicesinpanel',panel); +if not(isempty(SET(no).Measure)) + [measure,slice] = viewfunctions('getmeasurecoords',panel); + x = nan; + y = nan; + xo = nan; %used to set other points not in this slice (measurementoutsideplane) + yo = nan; + + %This makes measurement text rendering compact and index will depend on + %number of measurements in the current timeframe and slice + if DATA.Pref.BackgroundColor + bgcolor = 'k'; + else + bgcolor = 'none'; + end + textcounter = 1; + for loop=1:length(SET(no).Measure) + ziv = round(measure(loop).Z); + ziv = min(ziv):max(ziv); + if any(ismember(slices,ziv)) && ... + (SET(no).Measure(loop).T==SET(no).CurrentTimeFrame)||(isnan(SET(no).Measure(loop).T)) + + %sometimes the column format is not used + if ~iscolumn(measure(loop).Y) + measure(loop).Y = measure(loop).Y'; + measure(loop).X = measure(loop).X'; + end + + if ~all(ismember(ziv , slices)) + DATA.Handles.measurement(panel).LineStyle = '--'; + else + DATA.Handles.measurement(panel).LineStyle = '-'; + end + + %if the current view is montage we need to translate the + %contour to the correct slice if the entire + if any(strcmp(DATA.ViewPanelsType{panel},{'montage','montagesegmented','montagerow'})) + for i = 1:length(ziv) + [x1,y1] = ind2sub(DATA.ViewPanelsMatrix{panel},find(ziv(i)==slices,1)); + x = [x;nan;scale*(measure(loop).Y+(x1-1)*SET(no).YSize)]; + y = [y;nan;scale*(measure(loop).X+(y1-1)*SET(no).XSize)]; + end + else + x = [x;nan;scale*(measure(loop).Y)]; + y = [y;nan;scale*(measure(loop).X)]; + curslice = SET(DATA.ViewPanels(panel)).CurrentSlice; %get current slice + logind = (round(measure(loop).Z) ~= curslice); %logical index to not in this slice + if sum(logind)>0 + xo = [xo;nan;scale*(measure(loop).Y(logind))]; + yo = [yo;nan;scale*(measure(loop).X(logind))]; + end + %This is used to place montage text correctly + x1 = 1; + y1 = 1; + end + + if ~DATA.Run + [ymax,ix] = max(measure(loop).Y); + + DATA.Handles.measurementtext(panel,textcounter).Position = scale*[... + ymax+1+(x1-1)*SET(no).YSize... + measure(loop).X(ix)+(y1-1)*SET(no).XSize]; + DATA.Handles.measurementtext(panel,textcounter).String = sprintf('%s\n%0.1f [mm]',SET(no).Measure(loop).Name,SET(no).Measure(loop).Length); + DATA.Handles.measurementtext(panel,textcounter).BackgroundColor = bgcolor; + textcounter = textcounter + 1; + end + end + end + + if ~DATA.Run + set(DATA.Handles.measurementtext(panel,textcounter:end),... + 'Position',[nan nan]); + end + DATA.Handles.measurement(panel).XData = x; + DATA.Handles.measurement(panel).YData = y; + DATA.Handles.measurementoutsideplane(panel).XData = xo; + DATA.Handles.measurementoutsideplane(panel).YData = yo; + end -%if DATA.Handles.configiconholder.findindented('outline')%SET(NO).LevelSet.View.Outline - outlinedraw3dp('r') -%end -%add points -displaypoints('r',ima) -%Update image -im = getoverlayimage('r'); -%Update image -set(imh,'cdata',im) -%zoom state -set(ima,... - 'xlim',SET(NO).LevelSet.View.RZoomState(1:2),... - 'ylim',SET(NO).LevelSet.View.RZoomState(3:4)); +%--------------------- +function draworthoanglehandle(panel) %#ok +%----------------------- +%This function adds the orthoangle handle to the ortho panel +global DATA SET +scale = viewfunctions('getscale',panel); +no = DATA.ViewPanels(panel); -%------------------ -function gupdate -%----------------- -%Update green image +if isnan(DATA.Handles.orthoanglehandle.XData) + %default is quarter from the image border + [x,y] = calcfunctions('calcplaneintersections',no,no,'orth','gla'); + + %this is the intersection point of all planeintersections + xc = SET(no).HLA.slice; + yc = SET(no).VLA.slice; + + %then we find in which direction on the gla line there is the most + %space and place the anglehandle point here. + val1 = norm([xc,yc]-[x(1),y(1)]); + val2 = norm([xc,yc]-[x(2),y(2)]); + + if val1 +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); + +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + originalno = no;% no actually shown in panel + no = SET(no).Flow.MagnitudeNo; + % resetting that current time frame is always the one that is shown in + % the panel + SET(no).CurrentTimeFrame = SET(originalno).CurrentTimeFrame; +end + +scale = viewfunctions('getscale',panel); +slicestoinclude = viewfunctions('slicesinpanel',panel); + +%Define colortypes. These are then used to concatenate into the correct +%index in the x,y variables which finally are dealt into the different +%color roi graphics objects.' +textreset = false; +if nargin == 1%colortypes + colortypes = 'cgbrwkym'; + set(DATA.Handles.roitext(panel,:),'Position',[nan nan]); + textreset = true; +end + +x = cell(1,length(colortypes)); +y = cell(1,length(colortypes)); + +%only work with rois that exist in the included slices +numroisinslice = nnz(cellfun(@(x,y) any(~isempty(x)) && any(x==slicestoinclude),{SET(no).Roi.Z})); +roistodo = find(cellfun(@(x,y,z) numroisinslice ~= 0 && any(~isempty(x)) && any(x==slicestoinclude) && ismember(y(1),colortypes) && any(~isempty(z)),{SET(no).Roi.Z},{SET(no).Roi.LineSpec},{SET(no).Roi.Area})); +if ~textreset + if numroisinslice <= 10 + if length(DATA.Handles.roitext(panel,:))> numroisinslice + %reset all roitexts that are left after using ctrl-z + set(DATA.Handles.roitext(panel,:),'Position',[nan nan]); + else + set(DATA.Handles.roitext(panel,1:numroisinslice),'Position',[nan nan]); + end + else + set(DATA.Handles.roitext(panel,:),'Position',[nan nan]); + end +end +linewidth = DATA.Pref.LineWidth; +if isempty(linewidth) + linewidth = 1; +end +if DATA.Pref.BackgroundColor + bgcolor = 'k'; +else + bgcolor = 'none'; +end +%KG: +for loop = 1:length(roistodo) + %KG: + [xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slicestoinclude==SET(no).Roi(roistodo(loop)).Z)); + yl = (yl-1)*SET(no).XSize; + xl = (xl-1)*SET(no).YSize; + if roistodo(loop) == SET(no).RoiCurrent + DATA.Handles.roicurrent(panel).XData = scale*(xl+SET(no).Roi(roistodo(loop)).Y(:,SET(no).CurrentTimeFrame)); + DATA.Handles.roicurrent(panel).YData = scale*(yl+SET(no).Roi(roistodo(loop)).X(:,SET(no).CurrentTimeFrame)); + DATA.Handles.roicurrent(panel).Color = SET(no).Roi(roistodo(loop)).LineSpec(1); + DATA.Handles.roicurrent(panel).LineWidth = linewidth + 1; + else + cind = regexp(colortypes,SET(no).Roi(roistodo(loop)).LineSpec(1)); + x{cind} = cat(1,x{cind},nan,xl+SET(no).Roi(roistodo(loop)).Y(:,SET(no).CurrentTimeFrame)); + y{cind} = cat(1,y{cind},nan,yl+SET(no).Roi(roistodo(loop)).X(:,SET(no).CurrentTimeFrame)); + DATA.Handles.([colortypes(cind),'roi'])(panel).LineWidth = linewidth; + end end -%if DATA.Handles.configiconholder.findindented('outline') - outlinedraw3dp('g') -%end +if ~DATA.Run + %We only display text in one and orth viewmode + if any(strcmp(DATA.ViewPanelsType{panel},{'one','orth'})) + textloop = 1; + for loop = 1:length(roistodo) + %if ~all(isnan(SET(no).Roi(roistodo(loop)).Y(:,SET(no).CurrentTimeFrame))) + %get sign for text + %KG: + if SET(no).Roi(roistodo(loop)).Sign > 0 + roisign = ''; + else + roisign = ' (-)'; + end +% % % cind = regexp(colortypes,SET(no).Roi((loop)).LineSpec(1)); + + %ROI position + + % we also need to check if the roitext is within the panel limits + % otherwise we dont plot the text + %[ymin,ix] = min(SET(no).Roi((loop)).Y(:,SET(no).CurrentTimeFrame)); + if numroisinslice <= 10 + %This checks if it is a flow roi we are dealing with (do we have the output generated from calcflow in all timeframes). If so + %do not plot the Std and Mean intensities. + if ~isempty(SET(no).Flow) + [ymin,ix] = min(SET(no).Roi(roistodo(loop)).Y(:,SET(no).CurrentTimeFrame)); + ypos = ymin-1; + xpos = SET(no).Roi(roistodo(loop)).X(ix,SET(no).CurrentTimeFrame); + halign = 'right'; + if isempty(SET(no).Roi(roistodo(loop)).Area) + labelstr = sprintf('%s%s',SET(no).Roi(roistodo(loop)).Name,roisign); + else + labelstr = sprintf('%s%s\n%3.1f [cm^2]',... + SET(no).Roi(roistodo(loop)).Name,roisign, ... + SET(no).Roi(roistodo(loop)).Area(SET(no).CurrentTimeFrame)); + end + else + ypos = mean(SET(no).Roi(roistodo(loop)).Y(:,SET(no).CurrentTimeFrame)); + xpos = mean(SET(no).Roi(roistodo(loop)).X(:,SET(no).CurrentTimeFrame)); + halign = 'left'; + labelstr = sprintf('%s%s\n%3.1f [cm^2]\n%3.1f +/- %3.1f',... + SET(no).Roi(roistodo(loop)).Name,roisign, ... + SET(no).Roi(roistodo(loop)).Area(SET(no).CurrentTimeFrame), ... + SET(no).Roi(roistodo(loop)).Mean(SET(no).CurrentTimeFrame), ... + SET(no).Roi(roistodo(loop)).StD(SET(no).CurrentTimeFrame)); + end + DATA.Handles.roitext(panel,(textloop)).Position = scale*[ypos xpos]; + DATA.Handles.roitext(panel,(textloop)).HorizontalAlignment = halign; + DATA.Handles.roitext(panel,(textloop)).String = labelstr; + DATA.Handles.roitext(panel,(textloop)).BackgroundColor = bgcolor; + + textloop = textloop+1; + end + end + else + %set the different colortypes + set(DATA.Handles.roitext(panel,:),'Position',[nan nan]); + end +end -%add points -displaypoints('g',ima) +%set the different colortypes +for i = 1:length(colortypes) + DATA.Handles.([colortypes(i),'roi'])(panel).XData = scale*x{i}; + DATA.Handles.([colortypes(i),'roi'])(panel).YData = scale*y{i}; +end -%Update image -im = getoverlayimage('g'); +%------------------------------ +function drawplaneintersections %#ok +%------------------------------ +global DATA SET -%Update image - set(imh,'cdata',im) - -%zoom state -set(ima,... - 'xlim',SET(NO).LevelSet.View.GZoomState(1:2),... - 'ylim',SET(NO).LevelSet.View.GZoomState(3:4)); +panels = find(DATA.ViewPanels); +for p1 = panels %this is the nos panel which we are going to plot in + if ~any(strcmp(DATA.ViewPanelsType{p1},{'montage','montagesegmented','montagerow'})) %dont plot plane intersections within montage views + scale = viewfunctions('getscale',p1); + for p2 = panels + if p1~= p2 + [x,y] = calcfunctions('calcplaneintersections',... + DATA.ViewPanels(p1),DATA.ViewPanels(p2),DATA.ViewPanelsType{p1},... + DATA.ViewPanelsType{p2});%,'one','one',DATA.slices(p1),DATA.slices(p2)); + + DATA.Handles.planeintersection(p1,p2).YData = scale*x; + DATA.Handles.planeintersection(p1,p2).XData = scale*y; + if p2 == DATA.CurrentPanel + DATA.Handles.planeintersection(p1,p2).Color = 'y'; + else + DATA.Handles.planeintersection(p1,p2).Color = 'w'; + end + end + end + else + set(DATA.Handles.planeintersection(p1,:),'YData', nan, 'XData', nan); + end +end + +%---------------------- +function drawspeedimage %#ok +%---------------------- +%Ensure speedimage is updated. +global DATA -%------------------ -function bupdate -%----------------- -%Update blue image +drawimages(find(strcmp(DATA.ViewPanelsType,'speedim'))); +%----------------------- +function im = speedimage %#ok +%----------------------- +%generates the 3dp speed image in rgb format ready for display in segment global DATA SET NO -handles = DATA.Handles; -imh=handles.imagehandle(strcmp(DATA.ViewPanelsType,'cor3DP')); -ima=handles.imageaxes(strcmp(DATA.ViewPanelsType,'cor3DP')); +%--- generate 2D 'speed' image -if isempty(ima) - return +if isempty(SET(NO).LevelSet.SpeedIM) + segment3dp.tools('updatespeed'); end -%Add contour -%if DATA.Handles.configiconholder.findindented('outline')%SET(NO).LevelSet.View.Outline - outlinedraw3dp('b') -%end -%add points -displaypoints('b',ima) +tempimage = getimage(SET(NO).LevelSet.Pen.Color); -%Update image -im = getoverlayimage('b'); +%---Remap the image -%Update image - set(imh,'cdata',im) +%bug in fastremap and int16, then need to ensure it is in the range +if isa(tempimage,'int16') + tempremapped = fastremap(min(max(tempimage,int16(SET(NO).minValue)),int16(SET(NO).maxValue)),SET(NO).LevelSet.Speed.IntensityMap,int16(SET(NO).minValue),int16(SET(NO).maxValue)); +else + tempremapped = fastremap(tempimage,SET(NO).LevelSet.Speed.IntensityMap); + +end -%zoom state -set(ima,... - 'xlim',SET(NO).LevelSet.View.BZoomState(1:2),... - 'ylim',SET(NO).LevelSet.View.BZoomState(3:4)); +tempremapped = single(tempremapped)/4000+0.5; %scale it 0...1 +tempremapped = uint8(tempremapped*255)+1; %scale it to 1..256 -%----------------------------------- -function outlinedraw3dp(type) -%------------------------------------ -%Shows contour of 3d segmentation if outline button is indented and motion function isnt running. -global DATA SET NO +%convert colormap to uint8 +cmap = DATA.LevelSet.colormap; +cmap = uint8(255*cmap); +temprgb = cat(2,... + cmap(tempremapped,1),... + cmap(tempremapped,2),... + cmap(tempremapped,3)); + +im = reshape(temprgb,[size(tempimage,1), size(tempimage,2), 3]); + +%--------------------- +function drawimages(panel) +%----------------------- +global DATA SET -if ~DATA.Handles.configiconholder.findindented('outline') && ~DATA.LevelSet.motionon +% if isempty(DATA.ViewIM{panel}) && any(strcmp(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','cor3DP','speedim'})) +% im = createfunctions('createviewim',panel); +% DATA.Handles.imagehandles(panel).CData = im; +% return +if isempty(panel) return end -switch type - case 'r' - ima=DATA.Handles.imageaxes(strcmp(DATA.ViewPanelsType,'trans3DP')); - case 'g' - ima=DATA.Handles.imageaxes(strcmp(DATA.ViewPanelsType,'sag3DP')); - case 'b' - ima=DATA.Handles.imageaxes(strcmp(DATA.ViewPanelsType,'cor3DP')); - case 's' - ima=DATA.Handles.imageaxes(strcmp(DATA.ViewPanelsType,'speedim')); +if panel>length(DATA.ViewIM) || isempty(DATA.ViewIM{panel}) + createfunctions('createviewim',panel); end -if ~DATA.LevelSet.motionon - %delete(DATA.Handles.([type, 'contour'])) - set(DATA.Handles.([type, 'contour']),'visible','off') - hold(ima,'on'); - - % if speed im we want to use the current selected imagestack for contour. - if strcmp(type,'s') - im=double(getimagehelper(SET(NO).LevelSet.BW,SET(NO).LevelSet.Pen.Color)); - else - im = double(getimagehelper(SET(NO).LevelSet.BW,type)); - end - - if all(im==0) +%if any(strcmp(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','cor3DP','speedim'})) +switch DATA.ViewPanelsType{panel} + case 'trans3DP' + im = drawfunctions('getoverlayimage','r'); + set(DATA.Handles.imagehandles(panel),'CData',im,'XData',[1 size(im,2)],'YData',[1 size(im,1)]); return - end - - [~,DATA.Handles.([type, 'contour'])] = contour(... - ima,... - 0.5:size(im,2)-0.5,0.5:size(im,1)-0.5,im,[127 127]); - - switch type - case 'r' - set(DATA.Handles.([type, 'contour']),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''r'')','linecolor',[0 1 0]); - case 'b' - set(DATA.Handles.([type, 'contour']),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''b'')','linecolor',[0 1 0]); - case 'g' - set(DATA.Handles.([type, 'contour']),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''g'')','linecolor',[0 1 0]); - case 's' - set(DATA.Handles.([type, 'contour']),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''s'')','linecolor',[0 1 0]); - end - hold(ima,'off'); -else - set(DATA.Handles.([type, 'contour']),'Visible','off') -end - -%----------------------------------------- -function im = getimagehelper(vol,view) -%---------------------------------------- -%Similar as getimage, but do assme no TSize as stored locally in BW. - -global DATA SET NO - -switch lower(DATA.LevelSet.imageorientation) - case 'transversal' - switch view - case 'r' - im = squeeze(vol(:,:,SET(NO).LevelSet.View.RSlice)); - case 'g' - im = squeeze(vol(:,SET(NO).LevelSet.View.GSlice,:))'; - case 'b' - im = squeeze(vol(SET(NO).LevelSet.View.BSlice,:,:))'; - end; - case 'sagittal' - switch view - case 'r' - im = squeeze(vol(SET(NO).LevelSet.View.RSlice,:,:)); - case 'g' - im = squeeze(vol(:,:,SET(NO).LevelSet.View.GSlice)); - case 'b' - im = squeeze(vol(:,SET(NO).LevelSet.View.BSlice,:)); - end; - case 'coronal' - switch view - case 'r' - im = squeeze(vol(SET(NO).LevelSet.View.RSlice,:,:))'; - case 'g' - im = squeeze(vol(:,SET(NO).LevelSet.View.GSlice,:)); - case 'b' - im = squeeze(vol(:,:,SET(NO).LevelSet.View.BSlice)); - end; -end; - -%------------------------------ -function im = getimage(view) -%----------------------------- -%Get image for view given imageorientation, r = transversal, g = sagittal, -%b=coronal - -global DATA SET NO - -switch lower(DATA.LevelSet.imageorientation) - case 'transversal' - switch view - case 'r' - im = squeeze(SET(NO).IM(:,:,1,SET(NO).LevelSet.View.RSlice)); - case 'g' - im = squeeze(SET(NO).IM(:,SET(NO).LevelSet.View.GSlice,1,:))'; - case 'b' - im = squeeze(SET(NO).IM(SET(NO).LevelSet.View.BSlice,:,1,:))'; - end; - case 'sagittal' - switch view - case 'r' - im = squeeze(SET(NO).IM(SET(NO).LevelSet.View.RSlice,:,1,:)); - case 'g' - im = squeeze(SET(NO).IM(:,:,1,SET(NO).LevelSet.View.GSlice)); - case 'b' - im = squeeze(SET(NO).IM(:,SET(NO).LevelSet.View.BSlice,1,:)); - end; - case 'coronal' - switch view - case 'r' - im = squeeze(SET(NO).IM(SET(NO).LevelSet.View.RSlice,:,1,:))'; - case 'g' - im = squeeze(SET(NO).IM(:,SET(NO).LevelSet.View.GSlice,1,:)); - case 'b' - im = squeeze(SET(NO).IM(:,:,1,SET(NO).LevelSet.View.BSlice)); - end; -end; - -%---------------------------------------------- -function im = getoverlayimage(view,useroverlay) -%---------------------------------------------- -%Get image including overlay, view is either of 'r','g','b'. - -global SET NO - -im = getimage(view); -bw = getimagehelper(SET(NO).LevelSet.BW,view); -man = getimagehelper(SET(NO).LevelSet.Man,view); - -im = segment3dp.tools('levelsetremapandoverlay',im,bw,man); - -%-------------------------------- -function drawintensitymapping %#ok -%-------------------------------- -%Draws intensity mapping curve and add gray colorbar - -global DATA SET NO - -offset = SET(NO).LevelSet.IntensityOffset; -slope = SET(NO).LevelSet.IntensitySlope; -[minvalue,maxvalue] = segment3dp.tools('getminmax'); -windowmin = SET(NO).LevelSet.WindowCenter-SET(NO).LevelSet.WindowWidth/2; -windowmax = SET(NO).LevelSet.WindowCenter+SET(NO).LevelSet.WindowWidth/2; - -%Plot mapping-- -DATA.Handles.intensityline = plot(DATA.Handles.intensityaxes,... - [minvalue-abs(minvalue) -offset/slope (0.5-offset)/slope (1-offset)/slope maxvalue+abs(maxvalue)],... - [0 0 0.5 1 1],... - 'b-'); - -set(DATA.Handles.intensityaxes,'ytick',[0 1],... - 'yticklabel',{'0%' ,'100%'}); - -if isequal(SET(NO).Modality,'CT') %&& ~isempty(regexpi(class(SET(NO).IM),'int')) - mintext = sprintf('%d HU',round(windowmin)); - maxtext = sprintf('%d HU',round(windowmax)); - set(DATA.Handles.contrastlistbox,'visible','on'); -else - mintext = sprintf('%d',windowmin); - maxtext = sprintf('%d',windowmax); - set(DATA.Handles.contrastlistbox,'visible','off'); -end; - -set(DATA.Handles.intensityaxes,'xtick',... - [windowmin windowmax],... - 'xticklabel',{mintext maxtext}); - -%Add markers to move the lines -hold(DATA.Handles.intensityaxes,'on'); - -%x coordinates for the three points are: -x1 = max(windowmin,(0-offset)/slope); -x3 = min(windowmax,(1-offset)/slope); -x2 = (x1+x3)/2; - -%use linear algebra to find y coordinates, y = kx+m -y1 = x1*slope+offset; -y2 = x2*slope+offset; -y3 = x3*slope+offset; - -DATA.Handles.intensitypoint1 = plot(DATA.Handles.intensityaxes,windowmin,y1,'bo'); -DATA.Handles.intensitypoint2 = plot(DATA.Handles.intensityaxes,(windowmin+windowmax)/2,y2,'bo'); -DATA.Handles.intensitypoint3 = plot(DATA.Handles.intensityaxes,windowmax,y3,'bo'); - -set(DATA.Handles.intensitypoint1,'markersize',8,'buttondownfcn','segment3dp.tools(''intensitypoint1buttondown'')'); -set(DATA.Handles.intensitypoint2,'markersize',8,'buttondownfcn','segment3dp.tools(''intensitypoint2buttondown'')'); -set(DATA.Handles.intensitypoint3,'markersize',8,'buttondownfcn','segment3dp.tools(''intensitypoint3buttondown'')'); - -hold(DATA.Handles.intensityaxes,'off'); - -extra = (windowmax-windowmin)*0.1; -set(DATA.Handles.intensityaxes,'ylim',[-0.1 1.1],'xlim',[windowmin-extra windowmax+extra]); - -%-------------------------------------------------------- -function [x1,y1,x2,y2,x3,y3] = getpointcoordinates(no,x,y) -%-------------------------------------------------------- -%Get points on speedmapping - -global SET - -center = SET(no).LevelSet.Speed.Center; -width = SET(no).LevelSet.Speed.Width; -type = SET(no).LevelSet.Speed.MappingMode; - -%Get x-coordinate for points -switch type - case {'positiveslope','negativeslope'} - x1 = center-width/2; - x2 = center; - x3 = center+width/2; - case 'gaussian' - [~,ind] = find(y>=0,1,'first'); - x1 = x(ind); - x2 = center; - [~,ind] = find(y>=0,1,'last'); - x3 = x(ind); -end; - -%Ensure visible on screen -if x1<(center-width/2) - x1 = center-width/2; -end; - -if x3>(center+width/2) - x3 = center+width/2; -end; - -%Find y-coordinates -y1 = interp1(x,y,x1); -y2 = interp1(x,y,x2); -y3 = interp1(x,y,x3); - -%------------------------- -function updatemapping %#ok -%------------------------- -%update the mapping graphically - -global DATA SET NO - -%y = k(x-offset) - -[x,y] = segment3dp.tools('getmappingline',NO); - -SET(NO).LevelSet.Speed.IntensityMap = int16(2000*y); - -[x1,y1,x2,y2,x3,y3] = getpointcoordinates(NO,x,y); - -set(DATA.Handles.speedimline,'xdata',x,'ydata',y); -set(DATA.Handles.speedpoint1,'xdata',x1,'ydata',y1); -set(DATA.Handles.speedpoint2,'xdata',x2,'ydata',y2); -set(DATA.Handles.speedpoint3,'xdata',x3,'ydata',y3); - -%---------------------- -function drawmapping %#ok -%---------------------- -%Prepare the mapping area for drawing - -global DATA SET NO - -windowmin = min(SET(NO).LevelSet.WindowCenter-SET(NO).LevelSet.WindowWidth/2,SET(NO).LevelSet.Speed.Center-SET(NO).LevelSet.Speed.Width/2); -windowmax = max(SET(NO).LevelSet.WindowCenter+SET(NO).LevelSet.WindowWidth/2,SET(NO).LevelSet.Speed.Center+SET(NO).LevelSet.Speed.Width/2); - -%Plot mapping -[x,y] = segment3dp.tools('getmappingline',NO); -DATA.Handles.speedimline = plot(DATA.Handles.mappingaxes,x,y,'b-'); - -set(DATA.Handles.mappingaxes,'ytick',[-1 0 1],... - 'yticklabel',{'0%' '50%','100%'}); - -if isequal(SET(NO).Modality,'CT') %&& ~isempty(regexpi(class(SET(NO).IM),'int')) - mintext = sprintf('%d HU',round(windowmin)); - maxtext = sprintf('%d HU',round(windowmax)); -else - mintext = sprintf('%d',windowmin); - maxtext = sprintf('%d',windowmax); -end; - -set(DATA.Handles.mappingaxes,'xtick',[windowmin windowmax],... - 'xticklabel',{mintext maxtext}); - -%Plot center line -extra = (windowmax-windowmin)*0.1; -hold(DATA.Handles.mappingaxes,'on'); -plot(DATA.Handles.mappingaxes,[windowmin-extra windowmax+extra],[0 0],'k:'); - -%Get coordinates of the points -[x1,y1,x2,y2,x3,y3] = getpointcoordinates(NO,x,y); - -%Add markers to move the lines -DATA.Handles.speedpoint1 = plot(DATA.Handles.mappingaxes,x1,y1,'bo'); -DATA.Handles.speedpoint2 = plot(DATA.Handles.mappingaxes,x2,y2,'bo'); -DATA.Handles.speedpoint3 = plot(DATA.Handles.mappingaxes,x3,y3,'bo'); -set(DATA.Handles.speedpoint1,'markersize',8,'buttondownfcn','segment3dp.tools(''speedpoint1buttondown'')'); -set(DATA.Handles.speedpoint2,'markersize',8,'buttondownfcn','segment3dp.tools(''speedpoint2buttondown'')'); -set(DATA.Handles.speedpoint3,'markersize',8,'buttondownfcn','segment3dp.tools(''speedpoint3buttondown'')'); - -hold(DATA.Handles.mappingaxes,'off'); - -set(DATA.Handles.mappingaxes,'xlim',[windowmin-extra windowmax+extra],'ylim',[-1.05 1.05]); - -%Adjust color -c = [0 0 0]; -set(DATA.Handles.mappingaxes,'xcolor',c,'ycolor',c,'zcolor',c); - -%-------------------------------------- -function draw3dpimage(no,panel) -%-------------------------------------- -%Draws and initiates all necessary handles for a 3dp viewpanel - -global DATA SET - -segment('makeviewim',panel,no) - -%--- Draw image -axes(DATA.Handles.imageaxes(panel)); %Make sure draw in correct figure. -hold off - -switch DATA.ViewPanelsType{panel} - case 'trans3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','r',no); - zoomstate = SET(no).LevelSet.View.RZoomState; - case 'sag3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','g',no); - zoomstate = SET(no).LevelSet.View.GZoomState; - case 'cor3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','b',no); - zoomstate = SET(no).LevelSet.View.BZoomState; - case 'speedim' - switch DATA.ViewPanelsType{DATA.CurrentPanel} - case 'trans3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','r',no); - zoomstate = SET(no).LevelSet.View.RZoomState; - case 'sag3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','g',no); - zoomstate = SET(no).LevelSet.View.GZoomState; - case 'cor3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','b',no); - zoomstate = SET(no).LevelSet.View.BZoomState; - otherwise - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','r',no); - zoomstate = SET(no).LevelSet.View.RZoomState; - end -end - -%DATA.Handles.imagehandle(panel) = image([0.5, ysz-0.5],[0.5, xsz-0.5],DATA.ViewIM{panel}(:,:,:),'parent',DATA.Handles.imageaxes(panel)); -DATA.Handles.imagehandle(panel) = image([0, ysz],[0, xsz],DATA.ViewIM{panel}(:,:,:),'parent',DATA.Handles.imageaxes(panel)); - -set(DATA.Handles.imageaxes(panel),... - 'color',DATA.GUISettings.BackgroundColor,... - 'xtick',calcfunctions('calcticks',ysz,yres),... - 'ytick',calcfunctions('calcticks',xsz,xres),... - 'xticklabel',[],'yticklabel',[]); - -%Add objects -hold(DATA.Handles.imageaxes(panel),'on'); -switch DATA.ViewPanelsType{panel} - case 'trans3DP' - DATA.Handles.rbline = plot(DATA.Handles.imageaxes(panel),[0 size(DATA.ViewIM{panel},2)],[0 0],'b-'); %add lines, later correct in lineupdate; - DATA.Handles.rgline = plot(DATA.Handles.imageaxes(panel),[0 0],[0 size(DATA.ViewIM{panel},1)],'g-'); - DATA.Handles.rcontour = []; - DATA.Handles.rtext3dp = []; - displaypoints('r',DATA.Handles.imageaxes(panel)) - outlinedraw3dp('r') case 'sag3DP' - DATA.Handles.grline = plot(DATA.Handles.imageaxes(panel),[0 size(DATA.ViewIM{panel},2)],[0 0],'r-'); %add lines, later correct in lineupdate; - DATA.Handles.gbline = plot(DATA.Handles.imageaxes(panel),[0 0],[0 size(DATA.ViewIM{panel},1)],'b-'); - DATA.Handles.gcontour = []; - DATA.Handles.gtext3dp = []; - displaypoints('g',DATA.Handles.imageaxes(panel)) - outlinedraw3dp('g') + im = drawfunctions('getoverlayimage','g'); + set(DATA.Handles.imagehandles(panel),'CData',im,'XData',[1 size(im,2)],'YData',[1 size(im,1)]); + return case 'cor3DP' - DATA.Handles.brline = plot(DATA.Handles.imageaxes(panel),[0 size(DATA.ViewIM{panel},2)],[0 0],'r-'); %add lines, later correct in lineupdate; - DATA.Handles.bgline = plot(DATA.Handles.imageaxes(panel),[0 0],[0 size(DATA.ViewIM{panel},1)],'g-'); - DATA.Handles.bcontour = []; - DATA.Handles.btext3dp = []; - displaypoints('b',DATA.Handles.imageaxes(panel)) - outlinedraw3dp('b') + im = drawfunctions('getoverlayimage','b'); + set(DATA.Handles.imagehandles(panel),'CData',im,'XData',[1 size(im,2)],'YData',[1 size(im,1)]); + return case 'speedim' - DATA.Handles.scontour = []; - outlinedraw3dp('s') -end - -hold(DATA.Handles.imageaxes(panel),'on'); -DATA.Handles.scarcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.weightedscarcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.mocontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.moextentcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.marcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -hold(DATA.Handles.imageaxes(panel),'off'); - -set(DATA.Handles.imageaxes(panel),'dataaspectratio',... - [1/yres ... - 1/xres 1], 'xlim',zoomstate(1:2),'ylim',zoomstate(3:4)); - -%--- Turn on hold -hold(DATA.Handles.imageaxes(panel),'on'); - -%Add selected frame -DATA.Handles.selectslicehandle{panel} = []; - -nop = DATA.ViewPanels(panel); -if length(SET(nop).Linked)>1 - %Find what panels are the different data sets - temppanels = SET(nop).Linked; - panels = []; - for loop=1:length(temppanels) - temp = find(DATA.ViewPanels==temppanels(loop)); - panels = [panels;temp(:)]; %#ok - end; - linkaxes(DATA.Handles.imageaxes(panels),'xy'); -else - linkaxes(DATA.Handles.imageaxes(panel),'off'); -end; - -%--- Add centerline if rotated data set -hold(DATA.Handles.imageaxes(panel),'on'); -if SET(no).Rotated - DATA.Handles.centerline = plot(DATA.Handles.imageaxes(panel),... - [SET(no).RotationCenter SET(no).RotationCenter],... - [0 SET(no).XSize],'c:'); -end; -hold(DATA.Handles.imageaxes(panel),'off'); - -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - -updatevisibility; -%----------------------------- -function drawimagepanel(panel) -%----------------------------- -%Draws selected panels, used upon loading or when when major -%changes have occured such as change of slice, added measurement -%points etc. This fcn is the true workhorse in graphics etc. - -global DATA SET - -if DATA.Silent - return; -end; - -if nargin < 1 - panel = DATA.CurrentPanel; -end - -if length(panel) == 1 - no = DATA.ViewPanels(panel); -else - no = DATA.ViewPanels(panel(1)); - if ~isempty(SET(no).Parent) - no = SET(no).Parent; - end -end - -%--- Find if to use viability -viashow = false; -if not(isempty(SET(no).Scar)) - if not(isequal(SET(no).Scar.Mode,'none')) - viashow = true; - end; -end; -stateandicon=segment('iconson',{'hidescar','hidemar','hideall'}); -state=stateandicon{1,1}; -if state%isequal(get(DATA.Handles.hidescaricon,'state'),'on') - viashow = false; -end; - -%--- Find out if to use MaR -marshow = false; -if not(isempty(SET(no).MaR)) - marshow = true; -end; -%stateandicon=segment('iconson','hidemar'); -state=stateandicon{2,1}; -if state%isequal(get(DATA.Handles.hidemaricon,'state'),'on') - marshow = false; -end; - -%--- Find out if to use overlays -olshow = false; -if not(isempty(SET(no).Overlay)) - olshow = true; - %stateandicon=segment('iconson','hidoverlay'); - state=stateandicon{3,1}; - - if state%isequal(get(DATA.Handles.hideoverlayicon,'state'),'on') - olshow = false; - end -end - -%--- Find panels that match no -%for panelloop=panelstodo; -if isequal(DATA.ViewPanelsType{panel},'mmodetemporal') - if (SET(no).TSize<2) - DATA.ViewPanelsType{panel} = 'one'; - end; - - %Make sure that mmodespatial exists. - foundit = false; - for loop=1:panel - if isequal(DATA.ViewPanelsType{loop},'mmodespatial') - foundit = true; - end; - end; - - if not(foundit) - myfailed('Can not show only mmode image.',DATA.GUI.Segment); - DATA.ViewPanelsType{panel} = 'one'; - end; -end; - -% %Make the panel visible -% set(DATA.Handles.imageaxes(panel),'visible','on'); - -%--- Check if normal/montage -switch DATA.ViewPanelsType{panel} - case {'one','mmodespatial','ortho','orthomip'} - drawimageone(panel,viashow,marshow,olshow) - case {'hla','vla','gla','hlamip','vlamip','glamip'} - drawimagehlavla(panel,viashow,marshow,olshow) - case {'montage','montagerow','montagefit','sax3','montagesegmented'} - drawimagemontage(panel,viashow,marshow) - case 'mmodetemporal' - drawimagemmode(no,panel); - case {'sag3DP','trans3DP','cor3DP','speedim'} - draw3dpimage(no,panel) - return - otherwise - myfailed(dprintf('Unknown image viewmode %s.',DATA.ViewPanelsType{panel}),DATA.GUI.Segment); -end; -DATA.updateaxestables('measure'); - -%Make the panel visible -set(DATA.Handles.imageaxes(panel),'visible','on'); - -%If is this panel is the current image panel then highlight -if isequal(DATA.CurrentPanel,panel)&&... - (DATA.GUISettings.MontageBorder||~ismember(DATA.ViewPanelsType{panel},{'montage','montagerow','montagefit','sax3'})) - - set(DATA.Handles.imageaxes(panel), 'xcolor',DATA.GUISettings.AxesColor,... - 'ycolor',DATA.GUISettings.AxesColor, 'linewidth',2.5, 'visible','on'); -else - set(DATA.Handles.imageaxes(panel),... - 'xcolor',[0 0 0],'ycolor',[0 0 0],... - 'linewidth',0.5,... - 'visible','off'); -end; - -set([... - DATA.Handles.endocontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel)],'linewidth',DATA.Pref.LineWidth); - -%--- Reset popup menus -set(DATA.Handles.selectcontextmenu,'Visible','off'); -set(DATA.Handles.endopinmenu,'Visible','off'); -set(DATA.Handles.epipinmenu,'Visible','off'); -set(DATA.Handles.rvendopinmenu,'Visible','off'); -set(DATA.Handles.roicontextmenu,'Visible','off'); -set(DATA.Handles.measurecontextmenu,'Visible','off'); -set(DATA.Handles.pointcontextmenu,'Visible','off'); -set(DATA.Handles.scarcontextmenu,'Visible','off'); -set(DATA.Handles.rvcontextmenu,'Visible','off'); -set(DATA.Handles.lvcontextmenu,'Visible','off'); -set(DATA.Handles.contrastcontextmenu,'Visible','off'); -%set(DATA.Handles.rvepipinmenu,'Visible','off'); - -viewupdateannotext(panel); -drawcolorbar(panel); - -%set(DATA.Handles.colorbar,'visible','off') - -if strcmp(DATA.CurrentTool,'orthoview') && ~DATA.isorthoview - updatetool('select'); -else - updatetool(DATA.CurrentTool,panel);%sets buttondown functions correctly according to current tool -end - -drawthumbnails(isempty(DATA.DATASETPREVIEW)); %EH - -if DATA.Pref.AutoSave - %Obsoleted - if (now-DATA.LastSaved)*24*60>5 - %More than 5 min ago. - h = msgbox('Autosaving'); - temp = DATA.Silent; - filemenu('savesegmentation_Callback',pwd,'autosave.seg'); - DATA.Silent = temp; - close(h); - DATA.LastSaved = now; - end; -end; - -%----------------------------- -function drawcontrastimage(no) %#ok -%----------------------------- -%draws contrast image - -global DATA NO - -if nargin < 1 - no = NO; -end - -panels = DATA.ViewPanels == no; -[DATA.ViewIM{panels}] = deal([]); -[DATA.Overlay(panels)] = deal(struct('alphadata',[],'cdata',[])); -%segment('makeviewim',DATA.CurrentPanel,no); -drawimageno(no); -segment('update_thumbnail',no); -if DATA.Pref.UseLight - DATA.BalloonLevel = -1; %Force update of ballonimage -end; - -%----------------------- -function drawthumbnails(calculatepreview,sliderupdated) -%----------------------- -%Draw all thumbnails. Calculatepreview is a boolean -%indicating if thumbnails needs to be redrawn. - -global DATA SET -persistent setlength - -if DATA.Silent || (~DATA.DataLoaded) || isempty(DATA.Handles.datasetaxes) - return; -end; - -if isempty(DATA.VisibleThumbnails) - DATA.VisibleThumbnails=1:min(DATA.Pref.NumberVisibleThumbnails,length(SET)); - setlength=length(SET); -end - -thumbsize=DATA.GUISettings.ThumbnailSize; -if nargin<2 ||(nargin==2 && not(sliderupdated)) - segment('updateslider'); -end - -if nargin<1 - calculatepreview=0; -end - -if setlength~=length(SET) - calculatepreview=1; -end -setlength=length(SET); - -if calculatepreview - calcfunctions('calcdatasetpreview'); -end - -DATA.Handles.datasetpreviewimage = image(DATA.DATASETPREVIEW,'parent',DATA.Handles.datasetaxes); -set(DATA.Handles.datasetpreviewimage,'ButtondownFcn',... - sprintf('%s(''thumbnail_Buttondown'')','segment')); -%colormap(DATA.Colormap); %no longer needed, now truecolor /JU -axis(DATA.Handles.datasetaxes,'image','off'); -ylim=[(DATA.VisibleThumbnails(1)-1) DATA.VisibleThumbnails(end)]*thumbsize+1; -set(DATA.Handles.datasetaxes,'ylim',ylim ,'dataaspectratio', [1 1 1]); -hold(DATA.Handles.datasetaxes,'on'); - -%draw frames -drawthumbnailframes; - -%print number of thumbnail in the upper left corner of the image -DATA.printthumbnailnumber(thumbsize); - -hold(DATA.Handles.datasetaxes,'off'); - -%--------------------------- -function drawthumbnailframes -%--------------------------- -%Draw frames around thumbnail images -global DATA SET NO - -if isempty(DATA.Handles.datasetaxes) - return -end - -thumbsize=DATA.GUISettings.ThumbnailSize; -try - delete(DATA.Handles.datasetpreviewline); - delete(DATA.Handles.datasetflowline); -catch %#ok -end - -hold(DATA.Handles.datasetaxes,'on'); -%Make frames used for linked images -%DATA.Handles.datasetselectline = []; -DATA.Handles.datasetflowline = []; -for loop=1:length(SET) - ypos = (loop-1)*thumbsize+1; - DATA.Handles.datasetflowline = ... - [DATA.Handles.datasetflowline ... - plot(DATA.Handles.datasetaxes,... - [1 1 thumbsize thumbsize 1 ],... - [ypos ypos+thumbsize-1 ypos+thumbsize-1 ypos ypos],... - 'color',DATA.GUISettings.ThumbFlowLineColor)... - ]; -end; -set(DATA.Handles.datasetflowline,'visible','off'); - -%Show frames around linked images -if length(SET(NO).Linked) > 1 - linkies = SET(NO).Linked(SET(NO).Linked ~= NO); - set(DATA.Handles.datasetflowline(linkies),'visible','on'); -end - -%draw frame around current image -ypos = (NO-1)*thumbsize+1; -DATA.Handles.datasetpreviewline = plot(DATA.Handles.datasetaxes,... - [1 1 thumbsize thumbsize 1 ],... - [ypos ypos+thumbsize-1 ypos+thumbsize-1 ypos ypos],... - 'color',DATA.GUISettings.ThumbLineColor); -% 'linewidth',2); - -% %Check current imageviewpanel -% montagestateandicon=segment('iconson','viewall'); -% onestateandicon=segment('iconson','viewone'); -% currenttype=DATA.ViewPanelsType{DATA.CurrentPanel}; -% switch currenttype -% case 'one' -% if ~onestateandicon{1} -% onestateandicon{2}.isindented=1; -% onestateandicon{2}.cdataDisplay=onestateandicon{2}.cdataIndent; -% montagestateandicon{2}.isindented=0; -% montagestateandicon{2}.cdataDisplay=montagestateandicon{2}.cdata; -% DATA.Handles.permanenticonholder.render -% end -% case 'montage' -% if ~montagestateandicon{1} -% onestateandicon{2}.isindented=0; -% onestateandicon{2}.cdataDisplay=onestateandicon{2}.cdata; -% montagestateandicon{2}.isindented=1; -% montagestateandicon{2}.cdataDisplay=montagestateandicon{2}.cdataIndent; -% DATA.Handles.permanenticonholder.render -% end -%end -%Updates viewbuttons zero is crucial else stack overflow -DATA.setviewbuttons(0) - -%------------------------ -function drawimageno(no) -%------------------------ -%Call drawimagepanel for the panels that contain no including flow -%panels. If no is not specified then the current image stack NO is -%used. This function is typically called when new objects have been -%created or modified. - -global DATA SET NO - -if DATA.Silent - return; -end; - -if nargin==0 - no = NO; -end; - -nos = SET(no).Linked; - -ind = []; -for loop=1:length(nos) - ind = [ind find(DATA.ViewPanels==nos(loop))]; %#ok -end; - -ind = unique(ind); %remove duplicates. -for loop=1:length(ind) - drawimagepanel(ind(loop)); - %adding XYZ coordinates to 3DPtab images - if isequal(DATA.CurrentTheme,'3dp')&& length(ind) == 4 ||... - isequal(DATA.CurrentTheme,'3dp')&& length(ind) == 2 - if ind(loop) ~= 2 - drawimagetypetext3dp(NO,ind(loop)) - updatevisibility - end - end - pause(0.05) -end; -% -% if nargin==0 -% %To fix intersection points at different image stacks. -% for loop=1:length(DATA.ViewPanels) -% % If not an index we've sent to imagepanel above, then slicepanel -% if ~ismember(DATA.ViewPanels(loop),DATA.ViewPanels(ind))&&(DATA.ViewPanels(loop)~=0) -% drawslicepanel(loop); -% end; -% end; -% end; - -% Contains enabler/disablers that need to be updated whenever T/ZSize -% has been changed. Rather than make the check at the instances (which -% could easily be forgotten when adding a new instances), they are called -% here. /JU -%Updates viewbuttons zero is crucial else stack overflow -%DATA.setviewbuttons(0) - -%segment('updateviewicons'); -%DATA.updateaxestables('flowclearall'); -%DATA.updateaxestables('volumeclearall'); - -%DATA.updateaxestables('measure'); -%DATA.updateaxestables('volume'); -%DATA.updateaxestables('flow'); - -showedits(no); -drawintersections; - -%-------------------------- -function drawintersections -%-------------------------- -%Draw intersections between image visible stacks. Uses -%calcplaneintersection to calculate intersection lines. -%This function respects view settings. - -global DATA - -if DATA.Silent - return; -end; - -for panel=1:length(DATA.ViewPanels) - - no = DATA.ViewPanels(panel); - - %Check if valid panel - if (DATA.ViewPanels(panel)>0)&&(ismember(DATA.ViewPanelsType{panel}, ... - {'one','ortho','hla','vla','gla','orthomip','hlamip','vlamip'})) - - %--- Delete old ones if existing. - try - delete(DATA.Handles.planeintersectionline{panel}) - delete(DATA.Handles.glarotatehandle(panel)) - catch %#ok - %do nothing - end; - - %Draw new one - stateandicon=segment('iconson','hideintersections'); - state=stateandicon{1}; - if not(state)%isequal(get(DATA.Handles.hideintersectionsicon,'state'),'off') - h = []; - hold(DATA.Handles.imageaxes(panel),'on'); - %current panel last to make sure orange line is not disabled - panelseq = [1:length(DATA.ViewPanels) DATA.CurrentPanel]; - panelseq(DATA.CurrentPanel) = []; - for loop = panelseq - %if (DATA.ViewPanels(loop)~=no)&&... - % (DATA.ViewPanels(loop)>0)&&... - % isequal(DATA.ViewPanelsType{loop},'one') - [x,y] = calcfunctions('calcplaneintersections',no, ... - DATA.ViewPanels(loop),DATA.ViewPanelsType{panel},DATA.ViewPanelsType{loop}); - h = [h;plot(DATA.Handles.imageaxes(panel),y,x,'w-');]; %#ok - if isequal(loop,DATA.CurrentPanel)&&~isempty(h)&&~isempty(x) - set(h(end),'color',DATA.GUISettings.IntersectColor); - end; - if ismember(DATA.ViewPanelsType{panel},{'one','ortho'}) && ... - strcmp(DATA.ViewPanelsType{loop},'gla') - [~,i] = sort(y); - DATA.Handles.glarotatehandle(panel) = plot(DATA.Handles.imageaxes(panel), ... - [nan y(i([1 end]))*[0.3;0.7]],[nan x(i([1 end]))*[0.3;0.7]],'bd'); - set(DATA.Handles.glarotatehandle(panel),'ButtonDownFcn', ... - 'segment(''glarotatehandle_Buttondown'')'); - end - end; - hold(DATA.Handles.imageaxes(panel),'off'); - DATA.Handles.planeintersectionline{panel} = h'; - if DATA.Pref.LineWidth>0 - set(h,'linewidth',DATA.Pref.LineWidth); - end; - %sets the same buttondownfunction for planeintersection as for - %imagehandle must be set here since drawintersections is called after drawintersections (which calls updatetool) in which buttondownfcn is updated. - if ishandle(DATA.Handles.imagehandle(panel)) - set(DATA.Handles.planeintersectionline{panel},'ButtonDownFcn',get(DATA.Handles.imagehandle(panel),'ButtonDownFcn')); - end - else - DATA.Handles.planeintersectionline{panel} = []; - end; - - end; %Valid panel - -end; %Loop over panel - -%---------------------- -function drawallslices %#ok -%---------------------- -%This fcn updates graphics in all visible image panels. - -global DATA NO - -noncurrentnos = setdiff(DATA.ViewPanels(DATA.ViewPanels > 0),NO); -for noloop = [noncurrentnos NO] - updatenopanels(noloop); -end - -%----------------------- -function drawsliceno(no) -%----------------------- -%Call updatenopanels -global NO - -if nargin < 1 - no = NO; -end -updatenopanels(no); - - -%-------------------------- -function updatenopanels(no,stateandicon) -%-------------------------- -%Update panels containing image stack no -global DATA SET -%profile on -panel = find(DATA.ViewPanels == no); -if isempty(panel) - %No panels to update - return -end -panelstype = DATA.ViewPanelsType(panel); -onepanels = panel(ismember(panelstype,{'one','mmodespatial','ortho'})); -mmodepanels = panel(strcmp(panelstype,'mmodespatial')); -montagepanels = panel(strcmp(panelstype,'montage')); -montagerowpanels = panel(strcmp(panelstype,'montagerow')); -montagefitpanels = panel(strcmp(panelstype,'montagefit')); -montagesegpanels = panel(strcmp(panelstype,'montagesegmented')); -montageallpanels = {montagepanels,montagerowpanels,montagefitpanels,montagesegpanels}; -sax3panels = panel(strcmp(panelstype,'sax3')); -orthomippanels = panel(strcmp(panelstype,'orthomip')); -hlapanels = panel(strcmp(panelstype,'hla')); -hlamippanels = panel(strcmp(panelstype,'hlamip')); -vlapanels = panel(strcmp(panelstype,'vla')); -vlamippanels = panel(strcmp(panelstype,'vlamip')); -glapanels = panel(strcmp(panelstype,'gla')); -panels3dp = panel(ismember(panelstype,{'trans3DP','speedim','sag3DP','cor3DP'})); -%Can supply state and icon for enhanced speed for example when dragging -%timebar. -if nargin <2 - stateandicon=segment('iconson',{'hidescar','hidemar','hideall','play'}); -end - -%Find if viability, for drawing contour only. -viashow = false; -if not(isempty(SET(no).Scar)) - if not(isequal(SET(no).Scar.Mode,'none')) - viashow = true; - end; -end; -if stateandicon{1,1}% isequal(get(DATA.Handles.hidescaricon,'state'),'on') - viashow = false; -end; - -%--- Find out if to use MaR -marshow = false; -if not(isempty(SET(no).MaR)) - marshow = true; -end; -if stateandicon{2,1}%isequal(get(DATA.Handles.hidemaricon,'state'),'on') - marshow = false; -end; - -%--- Find out if to use overlays -olshow = false; -if not(isempty(SET(no).Overlay)) - olshow = true; -end; -if stateandicon{3,1}%isequal(get(DATA.Handles.hideoverlayicon,'state'),'on') - olshow = false; -end; - -if DATA.Silent - return; -end; - -%stateandicon=segment('iconson','play'); -state=stateandicon{4,1}; - -if DATA.Run&&~state%not(isequal(get(DATA.Handles.playallicon,'state'),'on')) - SET(no).CurrentTimeFrame = segment('getframenumber'); - if length(SET(no).Linked) > 1 - nos = SET(no).Linked; - for nloop=1:length(nos) - SET(nos(nloop)).CurrentTimeFrame = SET(no).CurrentTimeFrame; - end; - end -end; - - -%--- Change definition of no so that ROI and contours points to -% magnitude data set. -cno = no; -if ~isempty(SET(no).Parent) - no = SET(no).Parent; -end; - -%Do things that require iteration -for panelloop = panel - %Make view im - if isempty(DATA.ViewIM{panelloop}) - segment('makeviewim',panelloop,no); - end - - %--- Viability contour - if (viashow) - delete(DATA.Handles.scarcontour{panelloop}); - try - delete(DATA.Handles.weightedscarcontour{panelloop}); - delete(DATA.Handles.moextentcontour{panelloop}); - delete(DATA.Handles.mocontour{panelloop}); - catch %#ok - end; - drawviabilityhelper(no,panelloop); - end - - %--- Mar contour - if (marshow) - try - delete(DATA.Handles.marcontour(panelloop)); - DATA.Handles.marcontour{panelloop} = []; - catch %#ok - end; - drawmarhelper(no,panelloop); - end; - - - if ismember(panelloop,onepanels) - %Atrial contour - if ~isempty(SET(no).AtrialScar) - atrialscar('drawsliceone',no,panel); - end; - end - - drawcolorbar; -end; - -%--- Do different update depending on viewMode -if ~isempty(onepanels) - if size(DATA.ViewIM{onepanels(1)},3) == 1 - if size(DATA.ViewIM{onepanels(1)},4) == 1 - set(DATA.Handles.imagehandle(onepanels),'cdata',... - DATA.ViewIM{onepanels(1)}(:,:,:)); - else - set(DATA.Handles.imagehandle(onepanels),'cdata',... - squeeze(DATA.ViewIM{onepanels(1)}(:,:,:,SET(no).CurrentSlice,:))); - end - else - if size(DATA.ViewIM{onepanels(1)},4) == 1 - set(DATA.Handles.imagehandle(onepanels),'cdata',... - squeeze(DATA.ViewIM{onepanels(1)}(:,:,SET(no).CurrentTimeFrame,:))); - else - set(DATA.Handles.imagehandle(onepanels),'cdata',... - squeeze(DATA.ViewIM{onepanels(1)}(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice,:))); - end - end - - if olshow - %Need to redraw and update panel frame if overlay - drawimageone(panel,viashow,marshow,olshow); - set(DATA.Handles.imageaxes,... - 'xcolor',[0 0 0],'ycolor',[0 0 0]); - set(DATA.Handles.imageaxes(DATA.CurrentPanel),... - 'xcolor',DATA.GUISettings.AxesColor,'ycolor',DATA.GUISettings.AxesColor,'linewidth',2.5); - return - end - - %--- Endo and epi contours - updatecontours(no,onepanels); - - %--- Pins - %updatepins(no,onepanels); - - %--- Interpolation points - updateinterp(no,onepanels); - - %Draw intersection with segmentation - updateintersectionpoints(onepanels); - - %--- Draw rois - updaterois(no,onepanels); - - %--- Display points - updateannotationpoints(no,onepanels); - - %--- Plot measures, time specific - updatemeasures(no,onepanels); - - %Update slicetimetext - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = dprintf('Slice:%02d',SET(no).CurrentSlice); - else - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).CurrentSlice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end - - if isnan(DATA.Handles.slicetimetext(onepanels)) - x = SET(no).YSize*0.9; - y = SET(no).XSize*0.9; - - DATA.Handles.slicetimetext(panel) = text(... - x,... - y,... - stri,'interpreter','none'); - extent = get(DATA.Handles.slicetimetext(panel),'extent'); - set(DATA.Handles.slicetimetext(panel),... - 'interpreter','none',... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-4*extent(4) 0]); - - % striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); - -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% y,... -% striZ,'interpreter','none'); -% extent = get(DATA.Handles.slicecoordtext(panel),'extent'); -% set(DATA.Handles.slicecoordtext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-5*extent(4) 0]); - else - set(DATA.Handles.slicetimetext(onepanels),'string',stri); -% %Update Z coodinates: -% striZ=dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% set(DATA.Handles.slicecoordtext(onepanels),'string',striZ); - viewupdatetextposition(onepanels); - viewupdateannotext(onepanels); - end - -end -for i = 1:4 - %loop over montage, montagerow, montagefit, montagesegmented panels - montagepanels = montageallpanels{i}; - if ~isempty(montagepanels) - %%%%%%%%%%%%%%% - %%% Montage %%% - %%%%%%%%%%%%%%% - - updatemodeldisplay(no,montagepanels(1)); - set(DATA.Handles.imagehandle(montagepanels),'cdata',squeeze(DATA.ViewIM{montagepanels(1)}(:,:,SET(no).CurrentTimeFrame,:))); - - % --- Endo and epi contours - updatemontagecontours(no,montagepanels); - - %--- Pins - updatemontagepins(no,montagepanels); - - %--- Interp Pts - updatemontageinterp(no,montagepanels); - - %--- Display ROI - updatemontagerois(no,montagepanels); - - %--- Display points - updatemontagepoints(no,montagepanels); - - %--- Plot measures, time specific, JU - updatemontagemeasures(no,montagepanels); - - %Update slicetimetext -% stri = dprintf('Time:%03d ms',round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); -% set(DATA.Handles.slicetimetext(montagepanels),'string',stri); -% -% %Update Z coordinate -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% set(DATA.Handles.slicecoordtext(montagepanels),'string',striZ); - - viewupdatetextposition(montagepanels); - viewupdateannotext(montagepanels); - end -end - -if ~isempty(sax3panels) - %%%%%%%%%%%%%% - %%%% SAX3 %%%% - %%%%%%%%%%%%%% - - DATA.updatesax3display(no,sax3panels(1)); - set(DATA.Handles.imagehandle(sax3panels),'cdata',squeeze(DATA.ViewIM{sax3panels(1)}(:,:,SET(no).CurrentTimeFrame,:))); - - % --- Endo and epi contours - updatesax3contours(no,sax3panels); - - %Update slicetimetext - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).CurrentSlice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - set(DATA.Handles.slicetimetext(sax3panels),'string',stri); - - %Update Z coordinate - striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); - set(DATA.Handles.slicecoordtext(sax3panels),'string',striZ); - - viewupdatetextposition(sax3panels); - viewupdateannotext(sax3panels); - -end; %Swith type of panel - -if ~isempty(hlapanels) - %Image data - set(DATA.Handles.imagehandle(hlapanels),'cdata',squeeze(DATA.ViewIM{hlapanels(1)}(:,:,SET(no).CurrentTimeFrame,:))); - - %Draw intersection with segmentation - updateintersectionpoints(hlapanels); - - %Update measures - updatemeasures(no,hlapanels); - - %Update slicetimetext - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = dprintf('Slice:%02d ',SET(no).HLA.slice); - else - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).HLA.slice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end - set(DATA.Handles.slicetimetext(hlapanels),'string',stri); - - %Update Z coordinate -% striZ = dprintf('Z:%.3f',SET(no).HLA.slice*((SET(no).SliceThickness+SET(no).SliceGap))); -% set(DATA.Handles.slicecoordtext(hlapanels),'string',striZ); - - viewupdatetextposition(hlapanels); - viewupdateannotext(hlapanels); -end -if ~isempty(vlapanels) - %Image data - set(DATA.Handles.imagehandle(vlapanels),'cdata',squeeze(DATA.ViewIM{vlapanels(1)}(:,:,SET(no).CurrentTimeFrame,:))); - - %Draw intersection with segmentation - updateintersectionpoints(vlapanels); - - %Update measures - updatemeasures(no,vlapanels); - - %Update slicetimetext - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = dprintf('Slice:%02d ',SET(no).VLA.slice); - else - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).VLA.slice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end - set(DATA.Handles.slicetimetext(vlapanels),'string',stri); -% - %Update Z coordinate -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% set(DATA.Handles.slicecoordtext(vlapanels),'string',striZ); - - viewupdatetextposition(vlapanels); - viewupdateannotext(vlapanels); -end - -mippanels = {orthomippanels,hlamippanels,vlamippanels}; -for i = 1:3 - panels = mippanels{i}; - if ~isempty(panels) - %Image data - set(DATA.Handles.imagehandle(panels),'cdata',squeeze(DATA.ViewIM{panels(1)}(:,:,SET(no).CurrentTimeFrame))); - - %Update slicetimetext - stri = dprintf('Time:%03d ms',round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - set(DATA.Handles.slicetimetext(panels),'string',stri); - - %Update Z coordinate -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% set(DATA.Handles.slicecoordtext(panels),'string',striZ); - - viewupdatetextposition(panels); - end -end -if ~isempty(glapanels) - %Image data - imsz = size(DATA.ViewIM{glapanels(1)}); - xsz = SET(no).ZSize; - ysz = size(DATA.ViewIM{glapanels(1)},2); %floor(abs(SET(pno).YSize*cos(glaangle))+SET(pno).XSize*sin(glaangle)); - glaangle = SET(no).GLA.angle; - xres = SET(no).SliceThickness + SET(no).SliceGap; - yres = SET(no).ResolutionY*cos(glaangle)+SET(no).ResolutionX*abs(sin(glaangle)); - updateglazoomstate(no,imsz(2)); - set(DATA.Handles.imagehandle(glapanels), ... - 'cdata',squeeze(DATA.ViewIM{glapanels(1)}(:,:,SET(no).CurrentTimeFrame,:)), ... - 'XData',[0.5 imsz(2)+0.5],'YData',[0.5 imsz(1)+0.5]); - set(DATA.Handles.imageaxes(glapanels),... - 'xlim',SET(no).GLA.ZoomState(1:2),... - 'ylim',SET(no).GLA.ZoomState(3:4),... - 'plotboxaspectratio',[ysz*yres xsz*xres 1], ... - 'dataaspectratio',[1/yres 1/xres 1]); - - %Draw intersection with segmentation - updateintersectionpoints(glapanels); - - %Update measures - updatemeasures(no,glapanels); - - %Update slicetimetext - - stri = dprintf(''); - - set(DATA.Handles.slicetimetext(glapanels),'string',stri); - - %Update Z coordinate -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% set(DATA.Handles.slicecoordtext(glapanels),'string',striZ); - - viewupdatetextposition(glapanels); - viewupdateannotext(glapanels); -end - -%--- Update timebar - -%Only update time slider and time text on current image stack -if SET(no).TSize>1 - %DATA.updatetimebaraxes; - t = SET(no).TimeVector*1000; - %profile on - if any(no == DATA.LVNO) - set(DATA.Handles.timebarlv,'xdata',... - t(SET(no).CurrentTimeFrame)*[1 1]) - - end - if no == DATA.FlowNO - set(DATA.Handles.timebarflow,'xdata',... - t(SET(no).CurrentTimeFrame)*[1 1]) - - end - %profile report - set(DATA.Handles.timebar,'xdata',... - t(SET(no).CurrentTimeFrame)*[1 1]); -end; - -showedits(no); -%showedits(no); -%updatetool(DATA.CurrentTool,panel) -updatevisibility; -%profile report -%----------------------------------------------- -function drawimagemontage(panel,viashow,marshow) -%----------------------------------------------- -%Main workhorse for creating montage view. -% - viashow is if viability data should be updated. -% - marshow is if MaR data should be updated. - -global DATA SET - -pno = DATA.ViewPanels(panel); -type = DATA.ViewPanelsType{panel}; - -if (~isempty(SET(pno).Scar))&&(SET(pno).ZSize>100) - if yesno('Viewing scar in all slices might take very long time. Revert to one slice?',[],DATA.GUI.Segment); - DATA.ViewPanelsType{panel} = 'one'; - drawimagepanel(panel); - return; - end; -end; - -no = pno; -if ~isempty(SET(pno).Parent) - no = SET(pno).Parent; -end; - -if isempty(DATA.ViewIM{panel}) - segment('makeviewim',panel,no); - if ismember(type,{'montagefit','sax3'}) - segment('updatemodeldisplay'); - end -elseif ismember(type,{'montagefit','sax3'}) && ... - (size(DATA.ViewIM{panel},2)-size(DATA.ViewIM{panel},1)) * ... - (DATA.ViewMatrix(1)-DATA.ViewMatrix(2)) < 0 - %Wrong orientation of view, make new viewim - segment('makeviewim',panel,no); - segment('updatemodeldisplay'); -elseif strcmp(type,'montagesegmented') - segment('makeviewim',panel,no); -end; -if strcmp(type,'sax3') - DATA.updatesax3display(no,panel); -else - updatemodeldisplay(no,panel); -end - -DATA.Handles.imagehandle(panel) = image(squeeze(DATA.ViewIM{panel}(:,:,SET(no).CurrentTimeFrame,:)),... - 'parent',DATA.Handles.imageaxes(panel)); -DATA.Handles.scarcontour{panel} = []; -DATA.Handles.weightedscarcontour{panel} = []; -DATA.Handles.mocontour{panel} = []; -DATA.Handles.moextentcontour{panel} = []; -DATA.Handles.marcontour{panel} = []; -%colormap(DATA.Handles.imageaxes(panel),DATA.Colormap); - -set(DATA.Handles.imageaxes(panel),... - 'color',[0 0 0],... - 'xtick',[],... - 'ytick',[],... - 'plotboxaspectratio',[... - size(DATA.ViewIM{panel},2)*SET(no).ResolutionY ... - size(DATA.ViewIM{panel},1)*SET(no).ResolutionX 1]); - -%Update zoom state -switch DATA.ViewPanelsType{panel} - case 'montage' - if isempty(SET(no).MontageZoomState) - SET(no).MontageZoomState = [0.5;size(DATA.ViewIM{panel},2)+0.5;0.5;size(DATA.ViewIM{panel},1)+0.5]; - end; - set(DATA.Handles.imageaxes(panel),... - 'xlim',SET(no).MontageZoomState(1:2),... - 'ylim',SET(no).MontageZoomState(3:4)); - case 'montagerow' - %Montagerow - if isempty(SET(no).MontageRowZoomState) - SET(no).MontageRowZoomState = [0.5;size(DATA.ViewIM{panel},2)+0.5;0.5;size(DATA.ViewIM{panel},1)+0.5]; - end; - set(DATA.Handles.imageaxes(panel),... - 'xlim',SET(no).MontageRowZoomState(1:2),... - 'ylim',SET(no).MontageRowZoomState(3:4)); - case 'montagesegmented' - %Montagesegmented - %if isempty(SET(no).MontageFitZoomState) - SET(no).MontageFitZoomState = [0.5;size(DATA.ViewIM{panel},2)+0.5;0.5;size(DATA.ViewIM{panel},1)+0.5]; - %end; - set(DATA.Handles.imageaxes(panel),... - 'xlim',SET(no).MontageFitZoomState(1:2),... - 'ylim',SET(no).MontageFitZoomState(3:4)); - case {'montagefit','sax3'} - %Montagefit - viewimsz = size(DATA.ViewIM{panel}); - if isempty(SET(no).MontageFitZoomState) - %ugly hack to get size of panel - set(DATA.Handles.imageaxes(panel),'Units','points'); - boxpos = get(DATA.Handles.imageaxes(panel),'Position'); - set(DATA.Handles.imageaxes(panel),'Units','normalized'); - - if viewimsz(1) < viewimsz(2) - ratio = (viewimsz(1)/boxpos(4))/(viewimsz(2)/boxpos(3)); - SET(no).MontageFitZoomState(1:2) = [0.5;viewimsz(2)*ratio+0.5]; - SET(no).MontageFitZoomState(3:4) = [0.5;viewimsz(1)+0.5]; - else - ratio = (viewimsz(2)/boxpos(3))/(viewimsz(1)/boxpos(4)); - SET(no).MontageFitZoomState(1:2) = [0.5;viewimsz(2)+0.5]; - SET(no).MontageFitZoomState(3:4) = [0.5;viewimsz(1)*ratio+0.5]; - end - end - - % if isempty(SET(no).MontageFitZoomState) - % SET(no).MontageFitZoomState = [0.5;viewimsz(2)*ratio2+0.5;0.5;viewimsz(1)*ratio1+0.5]; - % end; - - mfzs = SET(no).MontageFitZoomState; - xdif = mfzs(2)-mfzs(1); - ydif = mfzs(4)-mfzs(3); - %Display has changed, turn zoom state 90 degrees - if (viewimsz(2)-viewimsz(1))*(xdif-ydif) < 0 - SET(no).MontageFitZoomState = mfzs([3 4 1 2]); - mfzs = SET(no).MontageFitZoomState; - xdif = mfzs(2)-mfzs(1); - ydif = mfzs(4)-mfzs(3); - end - xlim = mean(mfzs(1:2)) + xdif*[-0.6 0.6]; - ylim = mean(mfzs(3:4)) + ydif*[-0.6 0.6]; - set(DATA.Handles.imageaxes(panel),... - 'xlim',xlim,... - 'ylim',ylim,... - 'plotboxaspectratio',[xdif * SET(no).ResolutionY ... - ydif * SET(no).ResolutionX 1]); -end; - -set(DATA.Handles.imageaxes(panel),'dataaspectratio',... - [1/SET(no).ResolutionY ... - 1/SET(no).ResolutionX 1]); - -%Draw box around slices -DATA.Handles.selectslicehandle{panel} = zeros(1,SET(no).ZSize); -hold(DATA.Handles.imageaxes(panel),'on'); - -%On a detailed scale, this box is in fact wrongly placed, but otherwise the -%sliceline ends up below other lines. /JU -if strcmp(DATA.ViewPanelsType{panel},'montagesegmented') -% slicestoinclude = find(findfunctions('findslicewithendo',no)+findfunctions('findslicewithepi',no)+findfunctions('findslicewithrvendo',no))'; -% if min(slicestoinclude) > 1 -% slicestoinclude = [min(slicestoinclude)-1 slicestoinclude]; -% end -% if max(slicestoinclude) < SET(no).ZSize; -% slicestoinclude = [slicestoinclude max(slicestoinclude)+1]; -% end - slicestoinclude = segment_main('getmontagesegmentedslices',no); -else - slicestoinclude = 1:SET(no).ZSize; -end -for zloop=1:numel(slicestoinclude) - loop = slicestoinclude(zloop); - x1 = 2.25+mod((zloop-1),DATA.ViewPanelsMatrix{panel}(2))*SET(no).YSize; - x2 = -2.5+x1+SET(no).YSize; - y1 = 2.25+floor((zloop-1)/DATA.ViewPanelsMatrix{panel}(2))*SET(no).XSize; - y2 = -2.5+y1+SET(no).XSize; - DATA.Handles.selectslicehandle{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - [x1 x2 x2 x1 x1],[y1 y1 y2 y2 y1],DATA.GUISettings.SliceLineSpec); - set(DATA.Handles.selectslicehandle{panel}(loop),'visible','off','linewidth',3); -end; - -%Activate currentslice -if isempty(SET(no).StartSlice) - SET(no).StartSlice = NaN; -end; -if isnan(SET(no).StartSlice)||(SET(no).StartSlice<0)||(SET(no).StartSlice>SET(no).ZSize) - SET(no).StartSlice=1; -end; -if isempty(SET(no).EndSlice) - SET(no).EndSlice = NaN; -end; -if isnan(SET(no).EndSlice)||(SET(no).EndSlice<0)||(SET(no).EndSlice>SET(no).ZSize) - SET(no).EndSlice=SET(no).ZSize; -end; - -set(DATA.Handles.selectslicehandle{panel}(SET(no).StartSlice:SET(no).EndSlice),'visible','on'); - -%--- Write text describing image type -drawmontageimagetypetext(no,pno,panel); - -%Add contours and pins - -drawmontagecontours(no,panel); -if strcmp(type,'sax3') - updatesax3contours(no,panel); -end - -%Intersections are not visible now. -DATA.Handles.planeintersectionline{panel} = []; -DATA.Handles.endointersectionline{panel} = []; -DATA.Handles.endointersectionpoints{panel} = []; -DATA.Handles.epiintersection{panel} = []; -DATA.Handles.rvendointersection{panel} = []; -DATA.Handles.rvepiintersection{panel} = []; - -% --- Viability contour -if (viashow) - drawviabilityhelper(pno,panel); -end - -% --- MaR contour -if (marshow) - drawmarhelper(pno,panel); -end - -%Endo & Epi pins -drawmontagepins(no,panel); - -%Endo & Epi interp -drawmontageinterp(no,panel); - -%Atrial contour -if ~isempty(SET(no).AtrialScar) - atrialscar('drawimagemontage',no,panel); -end; - -%--- Add measures -drawmontagemeasures(no,panel); - -%--- Add points -drawmontagepoints(no,panel); - -%--- Plot roi's if existing -DATA.plotrois(panel,no); - -%--- Plot center -hold(DATA.Handles.imageaxes(panel),'on'); -[tempx,tempy] = ndgrid(0:(DATA.ViewPanelsMatrix{panel}(1)-1),0:(DATA.ViewPanelsMatrix{panel}(2)-1)); -DATA.Handles.center{panel} = plot(... - DATA.Handles.imageaxes(panel),... - SET(no).CenterY+tempy(:)*SET(no).YSize,... - SET(no).CenterX+tempx(:)*SET(no).XSize,'+',... - 'color',DATA.centercrossdef); - -clear tempx tempy - - -%--- Plot cursor -DATA.Handles.cursor(panel) = plot(... - DATA.Handles.imageaxes(panel),... - SET(no).CenterY,SET(no).CenterX,'r-'); -set(DATA.Handles.cursor(panel),'visible','off'); -hold(DATA.Handles.imageaxes(panel),'off'); - -updatevisibility; - -%-------------------------------- -function drawimagemmode(no,panel) -%-------------------------------- -%Draw temporal mmode view -global DATA SET - -% Show the temporal part of the mmode view - -DATA.Handles.imagehandle(panel) = image([-1 2]*SET(no).TSize,[0 SET(no).XSize], ... - zeros(SET(no).XSize,3*SET(no).TSize,3),'parent',... - DATA.Handles.imageaxes(panel)); - -hold(DATA.Handles.imageaxes(panel),'on'); -temp = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -hold(DATA.Handles.imageaxes(panel),'off'); - -%Assign to an "empty handle" -DATA.Handles.endocontour(panel) = temp; -DATA.Handles.epicontour(panel) = temp; -DATA.Handles.rvendocontour(panel) = temp; -DATA.Handles.rvepicontour(panel) = temp; -DATA.Handles.cursor(panel) = temp; -DATA.Handles.roicontour{panel} = temp; -DATA.Handles.roitext{panel} = temp; -DATA.Handles.scarcontour{panel} = temp; -DATA.Handles.weightedscarcontour{panel} = temp; -DATA.Handles.mocontour{panel} = temp; -DATA.Handles.moextentcontour{panel} = temp; -DATA.Handles.marcontour{panel} = temp; -DATA.Handles.pointp{panel} = temp; -DATA.Handles.pointo{panel} = temp; -DATA.Handles.pointtext{panel} = temp; -DATA.Handles.measureline{panel} = {temp}; -DATA.Handles.measuretext{panel} = temp; -DATA.Handles.planeintersectionline{panel} = []; - -%--- Add lines in mmode display -hold(DATA.Handles.imageaxes(panel),'on'); -DATA.Handles.mmode1line = plot(DATA.Handles.imageaxes(panel),... - [0 SET(no).TSize+1],[SET(no).XSize/2-10 SET(no).XSize/2-10],'w:'); -DATA.Handles.mmode2line = plot(DATA.Handles.imageaxes(panel),... - [0 SET(no).TSize+1],[SET(no).XSize/2+10 SET(no).XSize/2+10],'w:'); -DATA.Handles.mmodetimebar1 = plot(DATA.Handles.imageaxes(panel),[1 1],[0 SET(no).XSize],'w:'); -DATA.Handles.mmodetimebar2 = plot(DATA.Handles.imageaxes(panel),[SET(no).TSize SET(no).TSize],[0 SET(no).XSize],'w:'); -hold(DATA.Handles.imageaxes(panel),'off'); - -%--- Button downs -set(DATA.Handles.mmode1line,'ButtonDownFcn',... - sprintf('%s(''mmode1line_Buttondown'',%d)','segment',panel)); -set(DATA.Handles.mmode2line,'ButtonDownFcn',... - sprintf('%s(''mmode2line_Buttondown'',%d)','segment',panel)); -set(DATA.Handles.mmodetimebar1,'ButtonDownFcn',... - sprintf('%s(''mmodetimebar1_Buttondown'',%d)','segment',panel)); -set(DATA.Handles.mmodetimebar2,'ButtonDownFcn',... - sprintf('%s(''mmodetimebar2_Buttondown'',%d)','segment',panel)); - -set(DATA.Handles.imageaxes(panel),... - 'color',[0 0 0],... - 'xtick',[],... - 'ytick',calcfunctions('calcticks',SET(no).XSize,SET(no).ResolutionX),... - 'xticklabel',[],'yticklabel',[]); - -segment('updatemmode'); %Displays mmode image -segment('updatemmodevisibility'); %Hide parts -segment('updatemmodeline'); %Draw correct mmode line - -%--Main image buttondown -pause(0.05); -updatetool; -updatevisibility; - -%-------------------------------------------------- -function drawimageone(panel,viashow,marshow,olshow) -%-------------------------------------------------- -%Main workhorse for creating view of one image slice. -%- viashow is whether to show viability -%- marshow is whether to show MaR -%- olshow is whether to show overlays or not. - -global DATA SET - -%%%%%%%%%%%%%%% -%%% ONE %%%%%%% -%%%%%%%%%%%%%%% - -pno = DATA.ViewPanels(panel); -no = pno; - -if isempty(DATA.ViewIM{panel}) - segment('makeviewim',panel,no); -end; - -% -if ~isempty(SET(pno).Parent) - no = SET(pno).Parent; -end; - -if length(SET(pno).Linked)<2 - linkaxes(DATA.Handles.imageaxes(panel),'off'); -end; - -%--- Draw image -axes(DATA.Handles.imageaxes(panel)); %Make sure draw in correct figure. -hold off - -xsz = SET(pno).XSize; -ysz = SET(pno).YSize; -xres = SET(pno).ResolutionX; -yres = SET(pno).ResolutionY; - -if size(DATA.ViewIM{panel},3) == 1 - if size(DATA.ViewIM{panel},4) == 1 - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],DATA.ViewIM{panel}(:,:,:),'parent',DATA.Handles.imageaxes(panel)); - else - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],squeeze(DATA.ViewIM{panel}(:,:,:,SET(no).CurrentSlice,:)),'parent',DATA.Handles.imageaxes(panel)); - end -else - if size(DATA.ViewIM{panel},4) == 1 - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],squeeze(DATA.ViewIM{panel}(:,:,SET(no).CurrentTimeFrame,:)),'parent',DATA.Handles.imageaxes(panel)); - else - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],squeeze(DATA.ViewIM{panel}(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice,:)),'parent',DATA.Handles.imageaxes(panel)); - end -end -set(DATA.Handles.imageaxes(panel),... - 'color',DATA.GUISettings.BackgroundColor,... - 'xtick',calcfunctions('calcticks',ysz,yres),... - 'ytick',calcfunctions('calcticks',xsz,xres),... - 'xticklabel',[],'yticklabel',[]); -hold(DATA.Handles.imageaxes(panel),'on'); -DATA.Handles.scarcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.weightedscarcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.mocontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.moextentcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.marcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -hold(DATA.Handles.imageaxes(panel),'off'); - -set(DATA.Handles.imageaxes(panel),'plotboxaspectratio',[... - ysz*yres ... - xsz*xres 1]); - - -%--- Update zoom state -if isempty(SET(no).NormalZoomState) - SET(no).NormalZoomState = [0.5;ysz+0.5;0.5;xsz+0.5]; -end; -set(DATA.Handles.imageaxes(panel),... - 'xlim',SET(no).NormalZoomState(1:2),... - 'ylim',SET(no).NormalZoomState(3:4)); - -set(DATA.Handles.imageaxes(panel),'dataaspectratio',... - [1/yres ... - 1/xres 1]); - -%--- Turn on hold -hold(DATA.Handles.imageaxes(panel),'on'); - -%--- Overlay -if (olshow) - overlay('draw',pno,panel,DATA.CurrentTheme); -end - -%Image type text -drawimagetypetext(no,pno,panel); - -%Draw contours of Endo, Epi, RVEndo and RVEpi. -drawcontours(no,panel); - -%Atrial contour -if ~isempty(SET(no).AtrialScar) - atrialscar('drawimageone',no,panel); -end; - -%--- Viability contour -if (viashow) - drawviabilityhelper(pno,panel); -end - -%--- MaR contour -if (marshow) - drawmarhelper(pno,panel); -end; - -%--- plot Interp points -drawinterp(no,panel,olshow); - -%--- plot pins -drawpins(no,panel); - -if ~ismember(DATA.ViewPanelsType{panel},{'orthomip'}) - %Plot intersection points - drawintersectionpoints(no,panel); -end - -%Used for ROI's etc. -DATA.Handles.cursor(panel) = plot(DATA.Handles.imageaxes(panel), ... - SET(no).CenterY,... - SET(no).CenterX,'y-'); -set(DATA.Handles.cursor(panel),'visible','off'); - -%Plot center cross -DATA.Handles.center{panel} = plot(DATA.Handles.imageaxes(panel),... - SET(no).CenterY, ... - SET(no).CenterX,'+', ... - 'color',DATA.centercrossdef); - -%--- Plot intersecting planes -DATA.Handles.planeintersectionline{panel} = []; - -%--- Plot measures -drawmeasures(no,panel); - -%--- Add points -drawannotationpoints(no,panel) - -%Add selected frame -DATA.Handles.selectslicehandle{panel} = []; - -%--- Fix axis and color of image -%colormap(DATA.Colormap); - -nop = DATA.ViewPanels(panel); -if length(SET(nop).Linked)>1 - %Find what panels are the different data sets - temppanels = SET(nop).Linked; - panels = []; - for loop=1:length(temppanels) - temp = find(DATA.ViewPanels==temppanels(loop)); - panels = [panels;temp(:)]; %#ok - end; - linkaxes(DATA.Handles.imageaxes(panels),'xy'); -else - linkaxes(DATA.Handles.imageaxes(panel),'off'); -end; - -%--- Plot roi's if existing -DATA.drawroiinpanel(panel); - -if isequal(DATA.ViewPanelsType{panel},'mmodespatial') - %--- Add mmode line - hold(DATA.Handles.imageaxes(panel),'on'); - DATA.Handles.mmodeline = plot(DATA.Handles.imageaxes(panel),... - [SET(no).Mmode.X SET(no).Mmode.X+1],... - [SET(no).Mmode.Y SET(no).Mmode.Y+1],'w-'); - DATA.Handles.mmodepoint1 = plot(DATA.Handles.imageaxes(panel),SET(no).Mmode.X,SET(no).Mmode.Y,'bo'); - DATA.Handles.mmodepoint2 = plot(DATA.Handles.imageaxes(panel),SET(no).Mmode.X,SET(no).Mmode.Y,'bo'); - DATA.Handles.mmodepointcenter = plot(DATA.Handles.imageaxes(panel),SET(no).Mmode.X,SET(no).Mmode.Y,'bd'); - DATA.Handles.mmodempoint1 = plot(DATA.Handles.imageaxes(panel),SET(no).Mmode.X,SET(no).Mmode.Y,'w+'); - DATA.Handles.mmodempoint2 = plot(DATA.Handles.imageaxes(panel),SET(no).Mmode.X,SET(no).Mmode.Y,'w+'); - hold(DATA.Handles.imageaxes(panel),'off'); - - %Set up button down things in mmode - set(DATA.Handles.mmodepointcenter,'ButtonDownFcn',... - sprintf('%s(''mmodecenter_Buttondown'',%d)','segment',panel)); - set(DATA.Handles.mmodepoint1,'ButtonDownFcn',... - sprintf('%s(''mmode1_Buttondown'',%d)','segment',panel)); - set(DATA.Handles.mmodepoint2,'ButtonDownFcn',... - sprintf('%s(''mmode2_Buttondown'',%d)','segment',panel)); - set(DATA.Handles.mmodempoint1,'ButtonDownFcn',... - sprintf('%s(''mmodepoint1_Buttondown'',%d)','segment',panel)); - set(DATA.Handles.mmodempoint2,'ButtonDownFcn',... - sprintf('%s(''mmodepoint2_Buttondown'',%d)','segment',panel)); - -end; - -%--- Add centerline if rotated data set -hold(DATA.Handles.imageaxes(panel),'on'); -if SET(no).Rotated - DATA.Handles.centerline = plot(DATA.Handles.imageaxes(panel),... - [SET(no).RotationCenter SET(no).RotationCenter],... - [0 SET(no).XSize],'c:'); -end; -hold(DATA.Handles.imageaxes(panel),'off'); - -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - -updatevisibility; - -%----------------------------------------------------- -function drawimagehlavla(panel,viashow,marshow,olshow) -%----------------------------------------------------- -%Main workhorse for creating view of one image slice. -%- viashow is whether to show viability -%- marshow is whether to show MaR -%- olshow is whether to show overlays or not. - -global DATA SET - -%%%%%%%%%%%%%%% -%%% HLA/VLA %%% -%%%%%%%%%%%%%%% - -pno = DATA.ViewPanels(panel); -no = pno; -type = DATA.ViewPanelsType{panel}; - -if isempty(DATA.ViewIM{panel}) - segment('makeviewim',panel,no); -end; - -if ~isempty(SET(pno).Parent) - no = SET(pno).Parent; -end; - -if length(SET(pno).Linked)<2 - linkaxes(DATA.Handles.imageaxes(panel),'off'); -end; - -%--- Draw image -axes(DATA.Handles.imageaxes(panel)); %Make sure draw in correct figure. -hold off - -switch type(1:3) - case 'hla' - xsz = SET(pno).ZSize; - ysz = SET(pno).YSize; - xres = SET(pno).SliceThickness + SET(pno).SliceGap; - yres = SET(pno).ResolutionY; - case 'vla' - xsz = SET(pno).ZSize; - ysz = SET(pno).XSize; - xres = SET(pno).SliceThickness + SET(pno).SliceGap; - yres = SET(pno).ResolutionX; - case 'gla' - %General longaxis. glaangle = 0 <=> HLA; glaangle = pi/2 <=> VLA - glaangle = SET(pno).GLA.angle; - xsz = SET(pno).ZSize; - ysz = size(DATA.ViewIM{panel},2); %floor(abs(SET(pno).YSize*cos(glaangle))+SET(pno).XSize*sin(glaangle)); - xres = SET(pno).SliceThickness + SET(pno).SliceGap; - %yres = SET(pno).ResolutionY*cos(glaangle)^2+SET(pno).ResolutionX*sin(glaangle)^2; - yres = SET(pno).ResolutionY*cos(glaangle)+SET(pno).ResolutionX*abs(sin(glaangle)); -end -if size(DATA.ViewIM{panel},3) == 1 - if size(DATA.ViewIM{panel},4) == 1 - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],DATA.ViewIM{panel}(:,:,:),'parent',DATA.Handles.imageaxes(panel)); - else - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],squeeze(DATA.ViewIM{panel}(:,:,:,SET(no).CurrentSlice,:)),'parent',DATA.Handles.imageaxes(panel)); - end -else - if size(DATA.ViewIM{panel},4) == 1 - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],squeeze(DATA.ViewIM{panel}(:,:,SET(no).CurrentTimeFrame,:)),'parent',DATA.Handles.imageaxes(panel)); - else - DATA.Handles.imagehandle(panel) = image([0.5 ysz+0.5],[0.5 xsz+0.5],squeeze(DATA.ViewIM{panel}(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice,:)),'parent',DATA.Handles.imageaxes(panel)); - end -end -set(DATA.Handles.imageaxes(panel),... - 'color',DATA.GUISettings.BackgroundColor,... - 'xtick',calcfunctions('calcticks',ysz,yres),... - 'ytick',calcfunctions('calcticks',xsz,xres),... - 'xticklabel',[],'yticklabel',[]); -hold(DATA.Handles.imageaxes(panel),'on'); -DATA.Handles.scarcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.weightedscarcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.mocontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.moextentcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.marcontour{panel} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -hold(DATA.Handles.imageaxes(panel),'off'); - -set(DATA.Handles.imageaxes(panel),'plotboxaspectratio',[... - ysz*yres ... - xsz*xres 1]); - -%--- Turn on hold -hold(DATA.Handles.imageaxes(panel),'on'); - -%Image type text -drawimagetypetext(no,pno,panel); - -if ismember(type,{'hla','vla','gla'}) - %Plot intersection points - drawintersectionpoints(no,panel); - - %Plot measures - drawmeasures(no,panel); -end - -%Used for ROI's etc. -DATA.Handles.cursor(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).CenterY,... - SET(no).CenterX,'y-'); -set(DATA.Handles.cursor(panel),'visible','off'); - -DATA.Handles.center{panel} = plot(DATA.Handles.imageaxes(panel),... - SET(no).CenterY, ... - SET(no).CenterX,'+', ... - 'color',DATA.centercrossdef); - -%--- Set up contour handles -DATA.Handles.endocontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,'r'); -DATA.Handles.epicontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,'g'); -DATA.Handles.rvendocontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,'m'); -DATA.Handles.rvepicontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,'c'); - -%--- Plot intersecting planes -DATA.Handles.planeintersectionline{panel} = []; - -%--- Set up points handles -DATA.Handles.pointp{panel} = []; -DATA.Handles.pointo{panel} = []; -DATA.Handles.pointtext{panel} = []; - -%Add selected frame -DATA.Handles.selectslicehandle{panel} = []; - -nop = DATA.ViewPanels(panel); -if length(SET(nop).Linked)>1 - %Find what panels are the different data sets - temppanels = SET(nop).Linked; - panels = []; - for loop=1:length(temppanels) - temp = find(DATA.ViewPanels==temppanels(loop)); - panels = [panels;temp(:)]; %#ok - end; - linkaxes(DATA.Handles.imageaxes(panels),'xy'); -else - linkaxes(DATA.Handles.imageaxes(panel),'off'); -end; - -%--- Update zoom state -viewtype = upper(type(1:3)); -if isempty(SET(no).(viewtype).ZoomState) - if ~strcmp(viewtype,'GLA') - SET(no).(viewtype).ZoomState = [0.5;ysz+0.5;0.5;xsz+0.5]; - else - updateglazoomstate(no,ysz); - end -end; -set(DATA.Handles.imageaxes(panel),... - 'xlim',SET(no).(viewtype).ZoomState(1:2),... - 'ylim',SET(no).(viewtype).ZoomState(3:4)); -set(DATA.Handles.imageaxes(panel),'dataaspectratio',... - [1/yres ... - 1/xres 1]); - -%Set up ROI handles do not plot -DATA.Handles.roitext{panel} = zeros(1,SET(no).RoiN); -DATA.Handles.roicontour{panel} = zeros(1,SET(no).RoiN); -hold(DATA.Handles.imageaxes(panel),'on'); -DATA.Handles.roicontour{panel}(:) = plot(DATA.Handles.imageaxes(panel),NaN,NaN); -DATA.Handles.roitext{panel}(:) = text(DATA.Handles.imageaxes(panel),0,0,''); -hold(DATA.Handles.imageaxes(panel),'off'); - -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); -updatevisibility; - - -%--------------------------------------- -function xyzcoordtextupdate3dp(panel) -%--------------------------------------- -%Writes xyz coordinates text in imagepanel - -global DATA SET NO -x = SET(NO).YSize*0.9; -y = SET(NO).XSize*0.9; - - -%if ~DATA.Handles.configiconholder.findindented('showcross') -if (strcmp(DATA.ViewPanelsType{panel},'sag3DP')); - stri=dprintf('Slice:%02d',SET(NO).LevelSet.View.GSlice); - set(DATA.Handles.slicetimetext3dp(panel),'string',stri) - - striZ = dprintf('Y:%.3f',SET(NO).LevelSet.View.GSlice*SET(NO).ResolutionY); - set(DATA.Handles.slicecoordtext3dp(panel),'string',striZ) - -elseif (strcmp(DATA.ViewPanelsType{panel},'trans3DP')); - - stri=dprintf('Slice:%02d',SET(NO).LevelSet.View.RSlice); - set(DATA.Handles.slicetimetext3dp(panel),'string',stri) - - striZ = dprintf('Z:%.3f',SET(NO).LevelSet.View.RSlice*((SET(NO).SliceThickness+SET(NO).SliceGap))); - set(DATA.Handles.slicecoordtext3dp(panel),'string',striZ) - -elseif (strcmp(DATA.ViewPanelsType{panel},'cor3DP')); - stri=dprintf('Slice:%02d',SET(NO).LevelSet.View.BSlice); - set(DATA.Handles.slicetimetext3dp(panel),'string',stri) - - striZ = dprintf('X:%.3f',SET(NO).LevelSet.View.BSlice*(SET(NO).ResolutionX)); - set(DATA.Handles.slicecoordtext3dp(panel),'string',striZ) - -elseif (strcmp(DATA.ViewPanelsType{panel},'speedim')); %to reject - stri=dprintf('X:%02d',SET(NO).LevelSet.View.BSlice); - set(DATA.Handles.slicetimetext3dp(panel),'string',stri) - - striZ = dprintf('X:%.3f',SET(NO).LevelSet.View.BSlice*(SET(NO).ResolutionX)); - set(DATA.Handles.slicecoordtext3dp(panel),'string',striZ) -end - -viewupdatetextposition3dp(panel); -% if any(strcmp(DATA.ViewPanelsType,'trans3DP')); -% set(handles.rgline,'visible','off'); -% set(handles.rbline,'visible','off'); -% end -% if any(strcmp(DATA.ViewPanelsType,'cor3DP')); -% set(handles.bgline,'visible','off'); -% set(handles.brline,'visible','off'); -% end - %return -%end - - - -%--------------------------------------- -function drawimagetypetext(no,pno,panel) -%--------------------------------------- -%Writes text describing image type in imagepanel - -global DATA SET -x = SET(no).YSize*0.9; -y = SET(no).XSize*0.9; - -%Image type -DATA.Handles.imagetypetext(panel) = text(... - x,... - y,... - strcat(SET(pno).ImageType,',',SET(pno).ImageViewPlane),... - 'interpreter','none',... - 'parent',DATA.Handles.imageaxes(panel)); - -extent = get(DATA.Handles.imagetypetext(panel),'extent'); -set(DATA.Handles.imagetypetext(panel),... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-extent(4) 0],'visible','on'); - -%seriesdescription -DATA.Handles.seriesdescriptiontext(panel) = text(... - x,... - y,... - SET(pno).SeriesDescription,... - 'interpreter','none',... - 'parent',DATA.Handles.imageaxes(panel)); -extent = get(DATA.Handles.seriesdescriptiontext(panel),'extent'); -set(DATA.Handles.seriesdescriptiontext(panel),... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-3*extent(4) 0]); - -%dicomimagetype -DATA.Handles.dicomimagetypetext(panel) = text(... - x,... - y,... - SET(pno).DICOMImageType,'interpreter','none'); -extent = get(DATA.Handles.dicomimagetypetext(panel),'extent'); -set(DATA.Handles.dicomimagetypetext(panel),... - 'interpreter','none',... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-2*extent(4) 0]); - - if isnan(SET(no).CurrentTimeFrame) - %guess that 1 is the currenttimeframe - SET(no).CurrentTimeFrame=1; - - end - -%slicetimeframetext -if strcmp(DATA.ViewPanelsType{panel},'hla') - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = dprintf('Slice:%02d ',SET(no).HLA.slice); - else - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).HLA.slice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end -elseif strcmp(DATA.ViewPanelsType{panel},'vla') - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = dprintf('Slice:%02d ',SET(no).VLA.slice); - else - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).VLA.slice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end - elseif strcmp(DATA.ViewPanelsType{panel},'gla') - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = dprintf(''); - else - stri = dprintf(''); - end -elseif ismember(DATA.ViewPanelsType{panel},{'orthomip','hlamip','vlamip'}) - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri = ''; - else - stri = dprintf('Time:%03d ms',round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end -else - if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) || numel(SET(no).TimeVector)==1 - stri = dprintf('Slice:%02d',SET(no).CurrentSlice); - else - stri = dprintf('Slice:%02d Time:%03d ms',SET(no).CurrentSlice,round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); - end -end -DATA.Handles.slicetimetext(panel) = text(... - x,... - y,... - stri,'interpreter','none'); - extent = get(DATA.Handles.slicetimetext(panel),'extent'); - set(DATA.Handles.slicetimetext(panel),... - 'interpreter','none',... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-4*extent(4) 0]); - -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); - -% if (strcmp(DATA.CurrentTheme,'3dp')) -% if (strcmp(DATA.ViewPanelsType{panel},'sag3DP')); -% stri=dprintf('Slice:%02d',SET(no).LevelSet.View.GSlice); -% DATA.Handles.slicetimetext(panel) = text(... -% x,... -% y,... -% stri,'interpreter','none'); -% extent = get(DATA.Handles.slicetimetext(panel),'extent'); -% set(DATA.Handles.slicetimetext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-4*extent(4) 0]); -% -% striZ = dprintf('Y:%.3f',SET(no).LevelSet.View.GSlice*SET(no).ResolutionY); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% -% elseif (strcmp(DATA.ViewPanelsType{panel},'trans3DP')); -% -% stri=dprintf('Slice:%02d',SET(no).LevelSet.View.RSlice); -% DATA.Handles.slicetimetext(panel) = text(... -% x,... -% y,... -% stri,'interpreter','none'); -% extent = get(DATA.Handles.slicetimetext(panel),'extent'); -% -% -% set(DATA.Handles.slicetimetext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-4*extent(4) 0]); -% -% -% striZ = dprintf('Z:%.3f',SET(no).LevelSet.View.RSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% -% elseif (strcmp(DATA.ViewPanelsType{panel},'cor3DP')); -% stri=dprintf('Slice:%02d',SET(no).LevelSet.View.BSlice); -% DATA.Handles.slicetimetext(panel) = text(... -% x,... -% y,... -% stri,'interpreter','none'); -% extent = get(DATA.Handles.slicetimetext(panel),'extent'); -% set(DATA.Handles.slicetimetext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-4*extent(4) 0]); -% -% striZ = dprintf('X:%.3f',SET(no).LevelSet.View.BSlice*(SET(no).ResolutionX)); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% -% elseif (strcmp(DATA.ViewPanelsType{panel},'speedim')); %to reject -% stri=dprintf('X:%02d',SET(no).LevelSet.View.BSlice); -% DATA.Handles.slicetimetext(panel) = text(... -% x,... -% y,... -% stri,'interpreter','none'); -% extent = get(DATA.Handles.slicetimetext(panel),'extent'); -% set(DATA.Handles.slicetimetext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-4*extent(4) 0]); -% -% striZ = dprintf('X:%.3f',SET(no).LevelSet.View.BSlice*(SET(no).ResolutionX)); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% end -% else -% DATA.Handles.slicetimetext(panel) = text(... -% x,... -% y,... -% stri,'interpreter','none'); -% extent = get(DATA.Handles.slicetimetext(panel),'extent'); -% set(DATA.Handles.slicetimetext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-4*extent(4) 0]); - -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% y,... -% striZ,'interpreter','none'); -% extent = get(DATA.Handles.slicecoordtext(panel),'extent'); -% set(DATA.Handles.slicecoordtext(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-5*extent(4) 0]); -% -% - %end - -viewupdatetextposition(panel); - - - -%------------------------------ -function drawcontours(no,panel) -%------------------------------ -%Initiate handles and draw endo- and epicardial contours of the LV and RV. -global DATA SET -%persistent endohandle -if DATA.Pref.BlackWhite - endocolor = 'w-'; - epicolor = 'w-'; - rvendocolor = 'w-'; - rvepicolor = 'w-'; -else - endocolor = 'r-'; - epicolor = 'g-'; - rvendocolor = 'm-'; - rvepicolor = 'c-'; -end -notlax = ~ismember(DATA.ViewPanelsType{panel}, ... - {'hla','vla','orthomip','hlamip','vlamip'}); - -%These are not always properly disposed of. But when? -%Endo -if ~isempty(SET(no).EndoX) && notlax - DATA.Handles.endocontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),endocolor); - %--- Sector grid - DATA.drawsectorgrid(no,panel); -else - DATA.Handles.endocontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,endocolor); -end;%endohandle = DATA.Handles.endocontour; - -%Epi -if ~isempty(SET(no).EpiX) && notlax - DATA.Handles.epicontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),epicolor); -else - DATA.Handles.epicontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,epicolor);%,'linewidth',2); -end; - -%RVEndo -if ~isempty(SET(no).RVEndoX) && notlax - DATA.Handles.rvendocontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),rvendocolor); -else - DATA.Handles.rvendocontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,rvendocolor); -end; - -%RVEpi -if ~isempty(SET(no).RVEpiX) && notlax - DATA.Handles.rvepicontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),rvepicolor); -else - DATA.Handles.rvepicontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,rvepicolor); -end; - -%-------------------------------- -function updatecontours(no,panel) -%-------------------------------- -%Update coordinates of contour handles of one view panels -global DATA SET - -if ~isempty(SET(no).EndoX) - set(DATA.Handles.endocontour(panel),... - 'xdata',SET(no).EndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - 'ydata',SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)); - - %Sector grid - DATA.drawsectorgrid(no,panel); -else - set(DATA.Handles.endocontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).RVEndoX) - set(DATA.Handles.rvendocontour(panel),... - 'xdata',SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - 'ydata',SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)); -else - set(DATA.Handles.rvendocontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).RVEpiX) - set(DATA.Handles.rvepicontour(panel),... - 'xdata',SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - 'ydata',SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)); -else - set(DATA.Handles.rvepicontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).EpiX) - set(DATA.Handles.epicontour(panel),... - 'xdata',SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice),... - 'ydata',SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)); -else - set(DATA.Handles.epicontour(panel),... - 'xdata',[],'ydata',[]); -end; - - -%------------------------------------- -function drawmontagecontours(no,panel) -%------------------------------------- -%Initiate handles and draw contours for montage view. -global DATA SET - -if DATA.Pref.BlackWhite - endocolor = 'w-'; - epicolor = 'w-'; - rvendocolor = 'w-'; - rvepicolor = 'w-'; -else - endocolor = 'r-'; - epicolor = 'g-'; - rvendocolor = 'm-'; - rvepicolor = 'c-'; -end - -%Endo -if ~isempty(SET(no).EndoX) - DATA.Handles.endocontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EndoYView(:,SET(no).CurrentTimeFrame),... - SET(no).EndoXView(:,SET(no).CurrentTimeFrame),endocolor); -else - DATA.Handles.endocontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,endocolor); -end; -%Epi -if ~isempty(SET(no).EpiX) - DATA.Handles.epicontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EpiYView(:,SET(no).CurrentTimeFrame),... - SET(no).EpiXView(:,SET(no).CurrentTimeFrame),epicolor); -else - DATA.Handles.epicontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,epicolor); -end; -%RVEndo -if ~isempty(SET(no).RVEndoX) - DATA.Handles.rvendocontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEndoYView(:,SET(no).CurrentTimeFrame),... - SET(no).RVEndoXView(:,SET(no).CurrentTimeFrame),rvendocolor); -else - DATA.Handles.rvendocontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,rvendocolor); -end; -%RVEpi -if ~isempty(SET(no).RVEpiX) - DATA.Handles.rvepicontour(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEpiYView(:,SET(no).CurrentTimeFrame),... - SET(no).RVEpiXView(:,SET(no).CurrentTimeFrame),rvepicolor); -else - DATA.Handles.rvepicontour(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,rvepicolor); -end; - -%--------------------------------------- -function updatemontagecontours(no,panel) -%--------------------------------------- -%Update coordinates of contour handles for montage image view -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoX) - set(DATA.Handles.endocontour(panel),... - 'xdata',SET(no).EndoYView(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).EndoXView(:,SET(no).CurrentTimeFrame)); -else - set(DATA.Handles.endocontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).RVEndoX) - set(DATA.Handles.rvendocontour(panel),... - 'xdata',SET(no).RVEndoYView(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).RVEndoXView(:,SET(no).CurrentTimeFrame)); -else - set(DATA.Handles.rvendocontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).RVEpiX) - set(DATA.Handles.rvepicontour(panel),... - 'xdata',SET(no).RVEpiYView(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).RVEpiXView(:,SET(no).CurrentTimeFrame)); -else - set(DATA.Handles.rvepicontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).EpiX) - set(DATA.Handles.epicontour(panel),... - 'xdata',SET(no).EpiYView(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).EpiXView(:,SET(no).CurrentTimeFrame)); -else - set(DATA.Handles.epicontour(panel),... - 'xdata',[],'ydata',[]); -end; - -%------------------------------------ -function updatesax3contours(no,panel) -%------------------------------------ -%Update coordinates of contour handles for SAX3 image view -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoX) - set(DATA.Handles.endocontour(panel),... - 'xdata',SET(no).SAX3.EndoY(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).SAX3.EndoX(:,SET(no).CurrentTimeFrame)); -else - set(DATA.Handles.endocontour(panel),... - 'xdata',[],'ydata',[]); -end; -if ~isempty(SET(no).EpiX) - set(DATA.Handles.epicontour(panel),... - 'xdata',SET(no).SAX3.EpiY(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).SAX3.EpiX(:,SET(no).CurrentTimeFrame)); -else - set(DATA.Handles.epicontour(panel),... - 'xdata',[],'ydata',[]); -end; - -%-------------------------------------------- -function updatelongaxiscontours(arg,no,panel) -%-------------------------------------------- -%Update coordinates of contour handles for HLA or VLA image view -global DATA SET - -if nargin < 3 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoX) - set(DATA.Handles.endocontour(panel),... - 'xdata',SET(no).(arg).EndoY{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).(arg).EndoX{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.endocontour(panel),... - 'xdata',[],'ydata',[]); -end; -set(DATA.Handles.epicontour(panel),... - 'xdata',[],'ydata',[]); - -%----------------------------------- -function drawinterp(no,panel,olshow) -%----------------------------------- -%Initiate handles and draw interpolation points. -%Do not work well with overlays -global DATA SET - -if olshow || (isempty(SET(no).EndoInterpX)||isempty(SET(no).EndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice})) - DATA.Handles.endointerp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'rs','MarkerFaceColor','r','MarkerSize',4); -else - DATA.Handles.endointerp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).EndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'rs','MarkerFaceColor','r','MarkerSize',4); -end; -if olshow || (isempty(SET(no).EpiInterpX)||isempty(SET(no).EpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice})) - DATA.Handles.epiinterp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'gs','MarkerFaceColor','g','MarkerSize',4); -else - DATA.Handles.epiinterp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).EpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'gs','MarkerFaceColor','g','MarkerSize',4); -end; -if olshow || (isempty(SET(no).RVEndoInterpX)||isempty(SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice})) - DATA.Handles.rvendointerp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'ms','MarkerFaceColor','m','MarkerSize',4); -else - DATA.Handles.rvendointerp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ms','MarkerFaceColor','m','MarkerSize',4); -end; -if olshow || (isempty(SET(no).RVEpiInterpX)||isempty(SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice})) - DATA.Handles.rvepiinterp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'cs','MarkerFaceColor','c','MarkerSize',4); -else - DATA.Handles.rvepiinterp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'cs','MarkerFaceColor','c','MarkerSize',4); -end; - -%------------------------------ -function updateinterp(no,panel) -%------------------------------ -%Update coordinates of interpolation point handles -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoInterpX) - if size(SET(no).EndoInterpX,1)~=SET(no).TSize - tmpX = cell(SET(no).TSize,SET(no).ZSize); - tmpY = tmpX; - for i=1:size(SET(no).EndoInterpX,1) - for j=1:size(SET(no).EndoInterpX,2) - tmpX{i,j}=SET(no).EndoInterpX{i,j}; - tmpY{i,j}=SET(no).EndoInterpY{i,j}; - end - end - SET(no).EndoInterpX=tmpX; - SET(no).EndoInterpY=tmpY; - end - - set(DATA.Handles.endointerp(panel),... - 'xdata',SET(no).EndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).EndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.endointerp(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).EpiInterpX) - if size(SET(no).EpiInterpX,1)~=SET(no).TSize - tmpX = cell(SET(no).TSize,SET(no).ZSize); - tmpY = tmpX; - for i=1:size(SET(no).EpiInterpX,1) - for j=1:size(SET(no).EpiInterpX,2) - tmpX{i,j}=SET(no).EpiInterpX{i,j}; - tmpY{i,j}=SET(no).EpiInterpY{i,j}; - end - end - SET(no).EpiInterpX=tmpX; - SET(no).EpiInterpY=tmpY; - end - - set(DATA.Handles.epiinterp(panel),... - 'xdata',SET(no).EpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).EpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.epiinterp(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEndoInterpX) - if size(SET(no).RVEndoInterpX,1)~=SET(no).TSize - tmpX = cell(SET(no).TSize,SET(no).ZSize); - tmpY = tmpX; - for i=1:size(SET(no).RVEndoInterpX,1) - for j=1:size(SET(no).RVEndoInterpX,2) - tmpX{i,j}=SET(no).RVEndoInterpX{i,j}; - tmpY{i,j}=SET(no).RVEndoInterpY{i,j}; - end - end - SET(no).RVEndoInterpX=tmpX; - SET(no).RVEndoInterpY=tmpY; - end - - set(DATA.Handles.rvendointerp(panel),... - 'xdata',SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.rvendointerp(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEpiInterpX) - if size(SET(no).RVEpiInterpX,1)~=SET(no).TSize - tmpX = cell(SET(no).TSize,SET(no).ZSize); - tmpY = tmpX; - for i=1:size(SET(no).RVEpiInterpX,1) - for j=1:size(SET(no).RVEpiInterpX,2) - tmpX{i,j}=SET(no).RVEpiInterpX{i,j}; - tmpY{i,j}=SET(no).RVEpiInterpY{i,j}; - end - end - SET(no).RVEpiInterpX=tmpX; - SET(no).RVEpiInterpY=tmpY; - end - - set(DATA.Handles.rvepiinterp(panel),... - 'xdata',SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.rvepiinterp(panel),... - 'xdata',[],... - 'ydata',[]); -end; - -%----------------------------------- -function drawmontageinterp(no,panel) -%----------------------------------- -%Initiate handles and draw interpolation points for montage view -global DATA SET - -if isempty(SET(no).EndoInterpX)||isempty(SET(no).EndoInterpXView{SET(no).CurrentTimeFrame}) - DATA.Handles.endointerp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'rs','MarkerFaceColor','r','MarkerSize',3); -else - DATA.Handles.endointerp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EndoInterpYView{SET(no).CurrentTimeFrame},... - SET(no).EndoInterpXView{SET(no).CurrentTimeFrame},... - 'rs','MarkerFaceColor','r','MarkerSize',3); -end; -if isempty(SET(no).EpiInterpX)||isempty(SET(no).EpiInterpXView{SET(no).CurrentTimeFrame}) - DATA.Handles.epiinterp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'gs','MarkerFaceColor','g','MarkerSize',3); -else - DATA.Handles.epiinterp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EpiInterpYView{SET(no).CurrentTimeFrame},... - SET(no).EpiInterpXView{SET(no).CurrentTimeFrame},... - 'gs','MarkerFaceColor','g','MarkerSize',3); -end; -if isempty(SET(no).RVEndoInterpX)||isempty(SET(no).RVEndoInterpXView{SET(no).CurrentTimeFrame}) - DATA.Handles.rvendointerp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'ms','MarkerFaceColor','m','MarkerSize',3); -else - DATA.Handles.rvendointerp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEndoInterpYView{SET(no).CurrentTimeFrame},... - SET(no).RVEndoInterpXView{SET(no).CurrentTimeFrame},... - 'ms','MarkerFaceColor','m','MarkerSize',3); -end; -if isempty(SET(no).RVEpiInterpX)||isempty(SET(no).RVEpiInterpXView{SET(no).CurrentTimeFrame}) - DATA.Handles.rvepiinterp(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,... - 'cs','MarkerFaceColor','c','MarkerSize',3); -else - DATA.Handles.rvepiinterp(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEpiInterpYView{SET(no).CurrentTimeFrame},... - SET(no).RVEpiInterpXView{SET(no).CurrentTimeFrame},... - 'cs','MarkerFaceColor','c','MarkerSize',3); -end; - - - -%------------------------------------- -function updatemontageinterp(no,panel) -%------------------------------------- -%Update coordinates of interpolation point handles for montage view. -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoInterpX) - set(DATA.Handles.endointerp(panel),... - 'xdata',SET(no).EndoInterpYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).EndoInterpXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.endointerp(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).EpiInterpX) - set(DATA.Handles.epiinterp(panel),... - 'xdata',SET(no).EpiInterpYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).EpiInterpXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.epiinterp(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEndoInterpX) - set(DATA.Handles.rvendointerp(panel),... - 'xdata',SET(no).RVEndoInterpYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).RVEndoInterpXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.rvendointerp(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEpiInterpX) - set(DATA.Handles.rvepiinterp(panel),... - 'xdata',SET(no).RVEpiInterpYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).RVEpiInterpXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.rvepiinterp(panel),... - 'xdata',[],... - 'ydata',[]); -end; - -%-------------------------- -function drawpins(no,panel) -%-------------------------- -%Initiate handles and draw pins. -global DATA SET - -rpinstri = 'r+'; -gpinstri = 'g+'; -mpinstri = 'm+'; -cpinstri = 'c+'; - -if isempty(SET(no).EndoPinX)||isempty(SET(no).EndoPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}) - DATA.Handles.endopin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,rpinstri); -else - DATA.Handles.endopin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EndoPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).EndoPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},rpinstri); -end; -if isempty(SET(no).EpiPinX)||isempty(SET(no).EpiPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}) - DATA.Handles.epipin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,gpinstri); -else - DATA.Handles.epipin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EpiPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).EpiPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},gpinstri); -end; -if isempty(SET(no).RVEndoPinX)||isempty(SET(no).RVEndoPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}) - DATA.Handles.rvendopin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,mpinstri); -else - DATA.Handles.rvendopin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEndoPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).RVEndoPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},mpinstri); -end; -if isempty(SET(no).RVEpiPinX)||isempty(SET(no).RVEpiPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}) - DATA.Handles.rvepipin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,cpinstri); -else - DATA.Handles.rvepipin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEpiPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - SET(no).RVEpiPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},cpinstri); -end; - -set(DATA.Handles.endopin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''endo'')','segment')); -set(DATA.Handles.epipin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''epi'')','segment')); -set(DATA.Handles.rvendopin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''rvendo'')','segment')); -set(DATA.Handles.rvepipin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''rvepi'')','segment')); - -%---------------------------- -function updatepins(no,panel) -%---------------------------- -%Update coordinates of pin handles. -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoPinX) - set(DATA.Handles.endopin(panel),... - 'xdata',SET(no).EndoPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).EndoPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.endopin(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).EpiPinX) - set(DATA.Handles.epipin(panel),... - 'xdata',SET(no).EpiPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).EpiPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.epipin(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEndoPinX) - set(DATA.Handles.rvendopin(panel),... - 'xdata',SET(no).RVEndoPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).RVEndoPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.rvendopin(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEpiPinX) - set(DATA.Handles.rvepipin(panel),... - 'xdata',SET(no).RVEpiPinY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice},... - 'ydata',SET(no).RVEpiPinX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice}); -else - set(DATA.Handles.rvepipin(panel),... - 'xdata',[],... - 'ydata',[]); -end; - -%--------------------------------- -function drawmontagepins(no,panel) -%--------------------------------- -%Initiate handles and draw pins for montage view -global DATA SET - -%Color of pins -rpinstri = 'r+'; -gpinstri = 'g+'; -mpinstri = 'm+'; -cpinstri = 'c+'; - -if isempty(SET(no).EndoPinX)||isempty(SET(no).EndoPinXView{SET(no).CurrentTimeFrame}) - DATA.Handles.endopin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,rpinstri); -else - DATA.Handles.endopin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EndoPinYView{SET(no).CurrentTimeFrame},... - SET(no).EndoPinXView{SET(no).CurrentTimeFrame},rpinstri); -end; -if isempty(SET(no).EpiPinX)||isempty(SET(no).EpiPinXView{SET(no).CurrentTimeFrame}) - DATA.Handles.epipin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,gpinstri); -else - DATA.Handles.epipin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).EpiPinYView{SET(no).CurrentTimeFrame},... - SET(no).EpiPinXView{SET(no).CurrentTimeFrame},gpinstri); -end; -if isempty(SET(no).RVEndoPinX)||isempty(SET(no).RVEndoPinXView{SET(no).CurrentTimeFrame}) - DATA.Handles.rvendopin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,mpinstri); -else - DATA.Handles.rvendopin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEndoPinYView{SET(no).CurrentTimeFrame},... - SET(no).RVEndoPinXView{SET(no).CurrentTimeFrame},mpinstri); -end; -if isempty(SET(no).RVEpiPinX)||isempty(SET(no).RVEpiPinXView{SET(no).CurrentTimeFrame}) - DATA.Handles.rvepipin(panel) = plot(DATA.Handles.imageaxes(panel),NaN,NaN,cpinstri); -else - DATA.Handles.rvepipin(panel) = plot(DATA.Handles.imageaxes(panel),... - SET(no).RVEpiPinYView{SET(no).CurrentTimeFrame},... - SET(no).RVEpiPinXView{SET(no).CurrentTimeFrame},cpinstri); -end; -set(DATA.Handles.endopin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''endo'')','segment')); -set(DATA.Handles.epipin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''epi'')','segment')); -set(DATA.Handles.endopin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''rvendo'')','segment')); -set(DATA.Handles.epipin(panel),'ButtonDownFcn',... - sprintf('%s(''clickedpin_Callback'',''rvepi'')','segment')); - - - -%----------------------------------- -function updatemontagepins(no,panel) -%----------------------------------- -%Update coordinates of pin handles for montage view -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); -end - -if ~isempty(SET(no).EndoPinX) - set(DATA.Handles.endopin(panel),... - 'xdata',SET(no).EndoPinYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).EndoPinXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.endopin(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).EpiPinX) - set(DATA.Handles.epipin(panel),... - 'xdata',SET(no).EpiPinYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).EpiPinXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.epipin(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEndoPinX) - set(DATA.Handles.rvendopin(panel),... - 'xdata',SET(no).RVEndoPinYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).RVEndoPinXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.rvendopin(panel),... - 'xdata',[],... - 'ydata',[]); -end; -if ~isempty(SET(no).RVEpiPinX) - set(DATA.Handles.rvepipin(panel),... - 'xdata',SET(no).RVEpiPinYView{SET(no).CurrentTimeFrame},... - 'ydata',SET(no).RVEpiPinXView{SET(no).CurrentTimeFrame}); -else - set(DATA.Handles.rvepipin(panel),... - 'xdata',[],... - 'ydata',[]); -end; - -%---------------------------------------- -function drawintersectionpoints(no,panel) -%---------------------------------------- -%Initiate handles and draw intersections with other contours -global DATA - -if isempty(DATA.Handles.hideothercontouricon) || isequal(get(DATA.Handles.hideothercontouricon,'state'),'off') - [endointersectline,maxintersect] = segment('getendointersection',no); - viewtype = DATA.ViewPanelsType{panel}; - [endox,endoy] = calcfunctions('calcsegmentationintersections',no,'endo',viewtype); - [epix,epiy] = calcfunctions('calcsegmentationintersections',no,'epi',viewtype); - [rvendox,rvendoy] = calcfunctions('calcsegmentationintersections',no,'rvendo',viewtype); - [rvepix,rvepiy] = calcfunctions('calcsegmentationintersections',no,'rvepi',viewtype); - - DATA.Handles.endointersectionline{panel} = zeros(1,maxintersect); - for i=1:maxintersect - if(i<=length(endointersectline)) - n = endointersectline(i).NPoints; - DATA.Handles.endointersectionline{panel}(i) = plot(DATA.Handles.imageaxes(panel),... - endointersectline(i).Y(1:n),endointersectline(i).X(1:n),'r'); - else - % create empty handle for intersections in other time frames - DATA.Handles.endointersectionline{panel}(i) = plot(DATA.Handles.imageaxes(panel),... - [0 1],[0 1],'r'); - set(DATA.Handles.endointersectionline{panel}(i),'visible','off'); - end; - end; - DATA.Handles.endointersectionpoints{panel} = plot(DATA.Handles.imageaxes(panel),... - endoy,endox,'r.'); - DATA.Handles.epiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... - epiy,epix,'g.'); - DATA.Handles.rvendointersection{panel} = plot(DATA.Handles.imageaxes(panel),... - rvendoy,rvendox,'m.'); - DATA.Handles.rvepiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... - rvepiy,rvepix,'c.'); -else - for i = 1:length(DATA.Handles.endointersectionline{panel}) - DATA.Handles.endointersectionline{panel}(i) = plot(DATA.Handles.imageaxes(panel),... - NaN,NaN,'r'); - end; - DATA.Handles.endointersectionpoints{panel} = plot(DATA.Handles.imageaxes(panel),... - NaN,NaN,'r.'); - DATA.Handles.epiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... - NaN,NaN,'g.'); - DATA.Handles.rvendointersection{panel} = plot(DATA.Handles.imageaxes(panel),... - NaN,NaN,'m.'); - DATA.Handles.rvepiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... - NaN,NaN,'c.'); -end; - -if ~DATA.Pref.BlackWhite - set(DATA.Handles.endointersectionpoints{panel},'markersize',DATA.Pref.MarkerSize); - set(DATA.Handles.epiintersection{panel},'markersize',DATA.Pref.MarkerSize); - set(DATA.Handles.rvendointersection{panel},'markersize',DATA.Pref.MarkerSize); - set(DATA.Handles.rvepiintersection{panel},'markersize',DATA.Pref.MarkerSize); -else - set(DATA.Handles.endointersectionline{panel},'color',[1 1 1]); - set(DATA.Handles.endointersectionpoints{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); - set(DATA.Handles.epiintersection{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); - set(DATA.Handles.rvendointersection{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); - set(DATA.Handles.rvepiintersection{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); -end; - - -%--------------------------------------- -function updateintersectionpoints(panel) -%--------------------------------------- -%Draw intersection with segmentation in other image stacks - -global DATA -no = DATA.ViewPanels(panel(1)); -viewtype = DATA.ViewPanelsType{panel}; -if ~isequal(get(DATA.Handles.hideothercontouricon,'state'),'on') - endointersect = segment('getendointersection',no); - [endox,endoy] = calcfunctions('calcsegmentationintersections',no,'endo',viewtype); - [epix,epiy] = calcfunctions('calcsegmentationintersections',no,'epi',viewtype); - [rvendox,rvendoy] = calcfunctions('calcsegmentationintersections',no,'rvendo',viewtype); - [rvepix,rvepiy] = calcfunctions('calcsegmentationintersections',no,'rvepi',viewtype); - set(DATA.Handles.endointersectionline{panel},'visible','off'); - for i=1:length(endointersect) - n = endointersect(i).NPoints; - set(cellref(DATA.Handles.endointersectionline(panel),i),'xdata',endointersect(i).Y(1:n),... - 'ydata',endointersect(i).X(1:n),'visible','on'); - end; - if ~isempty([endox epix rvendox rvepix]) - set([DATA.Handles.endointersectionpoints{panel}], ... - 'XData',endoy,'YData',endox); - set([DATA.Handles.epiintersection{panel}], ... - 'XData',epiy,'YData',epix); - set([DATA.Handles.rvendointersection{panel}], ... - 'XData',rvendoy,'YData',rvendox); - set([DATA.Handles.rvepiintersection{panel}], ... - 'XData',rvepiy,'YData',rvepix); - end -end; - -%---------------------------- -function updaterois(no,panel) -%---------------------------- -%Update coordinates of ROI handles. -global DATA SET - -if nargin < 2 - panel = find(DATA.ViewPanels == no); + im = drawfunctions('speedimage'); + set(DATA.Handles.imagehandles(panel),'CData',im,'XData',[1 size(im,2)],'YData',[1 size(im,1)]); + return + case 'viewport' + return + case 'montagesegmented' + im = createfunctions('createviewim',panel); end -for loop=1:SET(no).RoiN - if ismember(SET(no).CurrentSlice,SET(no).Roi(loop).Z) && ... - ismember(SET(no).CurrentTimeFrame,SET(no).Roi(loop).T) - if SET(no).Roi(loop).Sign > 0 - roisign = ''; - else - roisign = ' (-)'; - end - set(cellref(DATA.Handles.roicontour(panel),loop),... - 'xdata',SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame),... - 'ydata',SET(no).Roi(loop).X(:,SET(no).CurrentTimeFrame)); - [ymin,ix] = min(SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame)); - set(cellref(DATA.Handles.roitext(panel),loop),... - 'position',... - [ymin-1 SET(no).Roi(loop).X(ix,SET(no).CurrentTimeFrame)], ... - 'String',{sprintf('%s%s',SET(no).Roi(loop).Name,roisign), ... - sprintf('%3.1f [cm^2]', ... - SET(no).Roi(loop).Area(SET(no).CurrentTimeFrame)), ... - sprintf('%3.1f ± %3.1f', ... - SET(no).Roi(loop).Mean(SET(no).CurrentTimeFrame), ... - SET(no).Roi(loop).StD(SET(no).CurrentTimeFrame))},... - 'HorizontalAlignment','right','VerticalAlignment','middle'); - if ismember(loop,SET(no).RoiCurrent) - set(cellref(DATA.Handles.roicontour(panel),loop), ... - 'LineWidth',DATA.Pref.LineWidth+1); - else - set(cellref(DATA.Handles.roicontour(panel),loop), ... - 'LineWidth',DATA.Pref.LineWidth); - end - else - set(cellref(DATA.Handles.roicontour(panel),loop), ... - 'XData',nan,'YData',nan); - set(cellref(DATA.Handles.roitext(panel),loop), ... - 'Position',[nan nan]); - end -end; - -% %update flow result panel -% if ~isempty(DATA.FlowNO) && ismember(DATA.FlowNO,SET(no).Linked) && ~isempty(DATA.FlowROI) -% if SET(no).RoiN <1 -% DATA.FlowROI = []; -% else -% calcfunctions('calcflow',no); -% end -% end -% DATA.updateaxestables('area',no); +if ndims(DATA.ViewIM{panel})==5 + im=squeeze(DATA.ViewIM{panel}(:,:,SET(DATA.ViewPanels(panel)).CurrentTimeFrame,:,:)); + DATA.Handles.imagehandles(panel).CData = im; +elseif ~isempty(SET(DATA.ViewPanels(panel)).Colormap) + DATA.Handles.imagehandles(panel).CData = ind2rgb(im,SET(DATA.ViewPanels(panel)).Colormap); +else + im = DATA.ViewIM{panel}(:,:,SET(DATA.ViewPanels(panel)).CurrentTimeFrame); + DATA.Handles.imagehandles(panel).CData = cat(3,im,im,im); +end +%Fix for interpolated. More work is required to verify this. +updatexydata('imagehandles',panel,size(im)); + +%-------------------------------- +function drawselectedframe(panel) %#ok +%-------------------------------- +%Function that highlights the selected panel -%----------------------------------- -function updatemontagerois(no,panel) -%----------------------------------- -%Update coordnates of ROI handles for montage view. -global DATA SET +global DATA -if nargin < 2 - panel = find(DATA.ViewPanels == no); +%turn all frames off +for p = 1:length(DATA.ViewPanels) + DATA.Handles.selectedframe(p).Visible = 'off'; end -roih = cat(1,DATA.Handles.roicontour{panel}); -for loop=1:SET(no).RoiN - [xofs,yofs] = calcfunctions('calcoffset', ... - SET(no).Roi(loop).Z,[],no,panel(1)); - set(roih(:,loop),... - 'xdata',SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame)+yofs,... - 'ydata',SET(no).Roi(loop).X(:,SET(no).CurrentTimeFrame)+xofs); - if ismember(loop,SET(no).RoiCurrent) - set(DATA.Handles.roicontour{panel}(loop), ... - 'LineWidth',DATA.Pref.LineWidth+1); - else - set(DATA.Handles.roicontour{panel}(loop), ... - 'LineWidth',DATA.Pref.LineWidth); - end -end; - +xl = DATA.Handles.imageaxes(panel).XLim; +yl = DATA.Handles.imageaxes(panel).YLim; +DATA.Handles.selectedframe(panel).XData =[xl,fliplr(xl),xl(1)]; +DATA.Handles.selectedframe(panel).YData =[yl(1),yl(1),yl(2),yl(2),yl(1)]; +DATA.Handles.selectedframe(panel).Visible = 'on'; -%------------------------------ -function drawmeasures(no,panel) -%------------------------------ -%Draw measurements, if available +%------------------------------------------------------------------------ +function drawselectedslice(panel) +%------------------------------------------------------------------------ +%Function that highlights the selected slice global DATA SET -if not(isempty(SET(no).Measure)) - DATA.Handles.measureline{panel} = cell(1,length(SET(no).Measure)); - DATA.Handles.measuretext{panel} = zeros(1,length(SET(no).Measure)); - if DATA.Pref.BackgroundColor - bgcolor = 'blue'; - else - bgcolor = 'none'; - end - [measure,slice] = segment('getmeasurecoords',no,panel); - for loop=1:length(measure) - % JU: Measures now time specific - % NL: Measures can now cross multiple slices - ziv = round(measure(loop).Z); - ziv = min(ziv):max(ziv); - if ismember(slice,ziv) && ... - ((SET(no).Measure(loop).T==SET(no).CurrentTimeFrame)||(isnan(SET(no).Measure(loop).T))) - - - %set(DATA.Handles.measureline{panel}{loop},'markersize',DATA.GUISettings.MeasureLineMarkerSize); - [ymax,ix] = max(measure(loop).Y); - DATA.Handles.measuretext{panel}(loop) = text(... - 'position',[ymax+1 measure(loop).X(ix)],... - 'string',sprintf('%s\n%0.1f [mm]',SET(no).Measure(loop).Name,SET(no).Measure(loop).Length),... - 'parent',DATA.Handles.imageaxes(panel),... - 'color',DATA.GUISettings.MeasureLineSpec{1},... - 'FontWeight','bold',... - 'interpreter','none','horizontalalignment','left','backgroundcolor',bgcolor); - DATA.Handles.measureline{panel}{loop} = plot(DATA.Handles.imageaxes(panel),... - measure(loop).Y,measure(loop).X,... - 'Color',DATA.GUISettings.MeasureLineSpec{1},... - 'Marker', DATA.GUISettings.MeasureLineSpec{2},... - 'LineStyle',DATA.GUISettings.MeasureLineSpec{3},... - 'linewidth',DATA.GUISettings.MeasureLineSpec{4},... - 'markersize',DATA.GUISettings.MeasureLineMarkerSize); - if ~all(ziv == slice) - set(DATA.Handles.measureline{panel}{loop},'LineStyle','--'); - end - DATA.measurefontsize(panel,loop); - else - DATA.Handles.measureline{panel}{loop} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); - DATA.Handles.measuretext{panel}(loop) = text(... - 'position',[NaN NaN],... - 'string','',... - 'parent',DATA.Handles.imageaxes(panel),'backgroundcolor',bgcolor); - end; - end; - set([DATA.Handles.measureline{panel}{:}; DATA.Handles.measuretext{panel}],'ButtondownFcn',... - sprintf('segment(''measurepoint_Buttondown'',%d)',panel)); -else - DATA.Handles.measureline{panel} = {}; - DATA.Handles.measuretext{panel} = []; -end; - -%-------------------------------- -function updatemeasures(no,panel) -%-------------------------------- -%Update coordinates of measurement handles -global DATA SET +no = DATA.ViewPanels(panel); -if nargin < 2 - panel = find(DATA.ViewPanels == no); +%if panels are in mode 'one'/'orth' or +%if user unselected all slices (start and end slices are empty), +%then no frame is shown +if any(strcmp(DATA.ViewPanelsType{panel},{'one','orth'}))||((isempty(SET(no).StartSlice))&&isempty(SET(no).EndSlice)) + DATA.Handles.selectedslice(panel).XData = nan; + DATA.Handles.selectedslice(panel).YData = nan; + return end -if not(isempty(SET(no).Measure)) - [measure,slice] = segment('getmeasurecoords',no,panel); - for loop=1:length(SET(no).Measure) - ziv = round(measure(loop).Z); - ziv = min(ziv):max(ziv); - if ismember(slice,ziv) && ... - (SET(no).Measure(loop).T==SET(no).CurrentTimeFrame)||(isnan(SET(no).Measure(loop).T)) - mlh = cellref(DATA.Handles.measureline(panel),loop); - set([mlh{:}],... - 'xdata', measure(loop).Y,... - 'ydata', measure(loop).X,... - 'Color',DATA.GUISettings.MeasureLineSpec{1},... - 'Marker', DATA.GUISettings.MeasureLineSpec{2},... - 'LineStyle',DATA.GUISettings.MeasureLineSpec{3},... - 'linewidth',DATA.GUISettings.MeasureLineSpec{4},... - 'markersize',DATA.GUISettings.MeasureLineMarkerSize); - if ~all(ziv == slice) - set([mlh{:}], ... - 'LineStyle','--'); - end - [ymax,ix] = max(measure(loop).Y); - set(cellref(DATA.Handles.measuretext(panel),loop),... - 'position',[ymax+1 measure(loop).X(ix)],... - 'string',sprintf('%s\n%0.1f [mm]',SET(no).Measure(loop).Name,SET(no).Measure(loop).Length),... - 'color',DATA.GUISettings.MeasureLineSpec{1},... - 'FontWeight','bold',... - 'interpreter','none',... - 'HorizontalAlignment','left','VerticalAlignment','middle'); - %'parent',DATA.Handles.imageaxes(panel),... - DATA.measurefontsize(panel,loop); - else - mlh = cellref(DATA.Handles.measureline(panel),loop); - set([mlh{:}],... - 'XData',nan,'YData',nan); - set(cellref(DATA.Handles.measuretext(panel),loop),... - 'Position',[nan nan]); - end; - end; - - -end; - -%------------------------------------- -function drawmontagemeasures(no,panel) -%------------------------------------- -%Initiate handles and draw measurements for montage view. -global DATA SET +slicestoinclude = viewfunctions('slicesinpanel',panel); -if not(isempty(SET(no).Measure)) - DATA.Handles.measureline{panel} = cell(1,length(SET(no).Measure)); - DATA.Handles.measuretext{panel} = zeros(1,length(SET(no).Measure)); - - for loop=1:length(SET(no).Measure) - if (SET(no).Measure(loop).T==SET(no).CurrentTimeFrame)||(isnan(SET(no).Measure(loop).T)) - %offsetx = SET(no).XSize*floor((SET(no).Measure(loop).Z-1)/DATA.ViewPanelsMatrix{panel}(2)); - %offsety = SET(no).YSize*mod(SET(no).Measure(loop).Z-1,DATA.ViewPanelsMatrix{panel}(2)); - ziv = min(SET(no).Measure(loop).Z):max(SET(no).Measure(loop).Z); - [offsetx,offsety] = calcfunctions('calcoffset', ... - ziv,[],no,panel); - [OFFSETY,MEASUREY] = ndgrid(SET(no).Measure(loop).Y,offsety); - [OFFSETX,MEASUREX] = ndgrid(SET(no).Measure(loop).X,offsetx); - DATA.Handles.measureline{panel}{loop} = plot(DATA.Handles.imageaxes(panel),... - OFFSETY+MEASUREY,... - OFFSETX+MEASUREX,... - 'Color',DATA.GUISettings.MeasureLineSpec{1},... - 'Marker', DATA.GUISettings.MeasureLineSpec{2},... - 'LineStyle',DATA.GUISettings.MeasureLineSpec{3},... - 'linewidth',DATA.GUISettings.MeasureLineSpec{4})'; - if size(OFFSETX,2) > 1 - set(DATA.Handles.measureline{panel}{loop},'LineStyle','--') - end - set(DATA.Handles.measureline{panel}{loop},'markersize',DATA.GUISettings.MeasureLineMarkerSize); - [ymax,ix] = max(SET(no).Measure(loop).Y); - DATA.Handles.measuretext{panel}(loop) = text(... - 'position',[offsety(end)+ymax+1 offsetx(end)+SET(no).Measure(loop).X(ix)],... - 'string',sprintf('%s\n%0.1f [mm]',SET(no).Measure(loop).Name,SET(no).Measure(loop).Length),... - 'color',DATA.GUISettings.MeasureLineSpec{1},... - 'parent',DATA.Handles.imageaxes(panel),... - 'interpreter','none',... - 'horizontalalignment','center'); - DATA.measurefontsize(panel,loop); - else - DATA.Handles.measureline{panel}{loop} = plot(DATA.Handles.imageaxes(panel),NaN,NaN); - DATA.Handles.measuretext{panel}(loop) = text(... - 'position',[NaN NaN],... - 'string','',... - 'parent',DATA.Handles.imageaxes(panel)); - end; - end; - set([DATA.Handles.measureline{panel}{:} DATA.Handles.measuretext{panel}],'ButtondownFcn',... - sprintf('segment(''measurepoint_Buttondown'',%d)',panel)); - - -else - DATA.Handles.measureline{panel} = {}; - DATA.Handles.measuretext{panel} = []; -end; +%create boxes +x = []; +y = []; -%--------------------------------------- -function updatemontagemeasures(no,panel) -%--------------------------------------- -%Update coordinates of measurement handles, for montage view. -global DATA SET +ss = find(SET(no).StartSlice==slicestoinclude); +se = find(SET(no).EndSlice==slicestoinclude); -if nargin < 2 - panel = find(DATA.ViewPanels == no); +for zloop=ss:se + [x1,y1] = ind2sub(DATA.ViewPanelsMatrix{panel},zloop); + x1 = (x1-1)*SET(no).YSize + 1.5; + y1 = (y1-1)*SET(no).XSize + 1.5; + x2 = -1.5+x1+SET(no).YSize; + y2 = -1.5+y1+SET(no).XSize; + x = [x nan x1 x2 x2 x1 x1];%nan separation creates separate box + y = [y nan y1 y1 y2 y2 y1]; end -lineh = cat(1,DATA.Handles.measureline{panel}); -texth = cat(1,DATA.Handles.measuretext{panel}); -if not(isempty(SET(no).Measure)) - - for loop=1:length(SET(no).Measure) - if ((SET(no).Measure(loop).T==SET(no).CurrentTimeFrame)||(isnan(SET(no).Measure(loop).T))) - ziv = min(SET(no).Measure(loop).Z):max(SET(no).Measure(loop).Z); - [offsetx,offsety] = calcfunctions('calcoffset', ... - ziv,[],no,panel(1)); - [OFFSETY,MEASUREY] = ndgrid(SET(no).Measure(loop).Y,offsety); - [OFFSETX,MEASUREX] = ndgrid(SET(no).Measure(loop).X,offsetx); - sz = size(OFFSETY); - set(lineh{:,loop},... - {'xdata'}, mat2cell(OFFSETY+MEASUREY,sz(1),ones(1,sz(2)))',... - {'ydata'}, mat2cell(OFFSETX+MEASUREX,sz(1),ones(1,sz(2)))',... - 'Color',DATA.GUISettings.MeasureLineSpec{1},... - 'Marker', DATA.GUISettings.MeasureLineSpec{2},... - 'LineStyle',DATA.GUISettings.MeasureLineSpec{3},... - 'linewidth',DATA.GUISettings.MeasureLineSpec{4},... - 'markersize',DATA.GUISettings.MeasureLineMarkerSize); - if sz(2) > 1 - set(lineh{:,loop},'LineStyle','--') - end - [ymax,ix] = max(SET(no).Measure(loop).Y); - set(texth(:,loop),... - 'position',[offsety(end)+ymax+1 offsetx(end)+SET(no).Measure(loop).X(ix)],... - 'string',sprintf('%s\n%0.1f [mm]',SET(no).Measure(loop).Name,SET(no).Measure(loop).Length),... - 'color',DATA.GUISettings.MeasureLineSpec{1},... - 'FontWeight','bold',... - 'interpreter','none','horizontalalignment','center'); - %'parent',DATA.Handles.imageaxes(panel),... - DATA.measurefontsize(panel,loop); - else - set(lineh{:,loop},'XData',nan,'YData',nan); - set(texth(:,loop),'Position',[nan nan]); - end; - end; - -end; - -%-------------------------------------- -function drawannotationpoints(no,panel) -%-------------------------------------- -%Draw annotation points, if available -global DATA SET - -if not(isempty(SET(no).Point)) - - markerSize=7; - lineSize=1; - %Input to force black background around corner text to improve visibility - if DATA.Pref.BackgroundColor - bgcolor = 'blue'; - else - bgcolor = 'none'; - end - - - DATA.Handles.pointp{panel} = zeros(1,length(SET(no).Point.X)); - DATA.Handles.pointo{panel} = DATA.Handles.pointp{panel}; - DATA.Handles.pointtext{panel} = DATA.Handles.pointp{panel}; - for loop=1:length(SET(no).Point.X) - if strcmp(SET(no).Point.Label(loop),'Ant track') || strcmp(SET(no).Point.Label(loop),'Inf track') || strcmp(SET(no).Point.Label(loop),'RV track') || strcmp(SET(no).Point.Label(loop),'Tracked Fwd') - - - DATA.Handles.pointtext{panel}(loop) = text(... - 'position',[SET(no).Point.Y(loop)+2 SET(no).Point.X(loop)],... - 'string',SET(no).Point.Label{loop},... - 'parent',DATA.Handles.imageaxes(panel),'backgroundcolor',bgcolor); - DATA.Handles.pointo{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - SET(no).Point.Y(loop),SET(no).Point.X(loop),'bo','linewidth', lineSize,'markersize', markerSize); - DATA.Handles.pointp{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - SET(no).Point.Y(loop),SET(no).Point.X(loop),'b+','linewidth', lineSize,'markersize', markerSize); - else +DATA.Handles.selectedslice(panel).XData = x; +DATA.Handles.selectedslice(panel).YData = y; - DATA.Handles.pointtext{panel}(loop) = text(... - 'position',[SET(no).Point.Y(loop)+2 SET(no).Point.X(loop)],... - 'string',SET(no).Point.Label{loop},... - 'parent',DATA.Handles.imageaxes(panel),'backgroundcolor',bgcolor); - DATA.Handles.pointp{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - SET(no).Point.Y(loop),SET(no).Point.X(loop),'w+'); - DATA.Handles.pointo{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - SET(no).Point.Y(loop),SET(no).Point.X(loop),'wo'); - end - - if isnan(SET(no).Point.T(loop)) - set(DATA.Handles.pointtext{panel}(loop),'fontweight','bold') - end; - hide = false; - if not(round(SET(no).Point.Z(loop))==SET(no).CurrentSlice) - hide = true; - end; - if (SET(no).Point.T(loop)~=SET(no).CurrentTimeFrame)&¬(isnan(SET(no).Point.T(loop))) - hide = true; - end; - if hide - set([DATA.Handles.pointp{panel}(loop) DATA.Handles.pointo{panel}(loop)], ... - 'XData',nan,'YData',nan); - set(DATA.Handles.pointtext{panel}(loop),'Position',[nan nan]); - end; - end; - set(DATA.Handles.pointtext{panel},'Color',[1 1 1]); - set([... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel}],'ButtonDownFcn',... - sprintf('%s(''pointat_Buttondown'', %d)','annotationpoint',panel)); - - -else - DATA.Handles.pointp{panel} = []; - DATA.Handles.pointo{panel} = []; - DATA.Handles.pointtext{panel} = []; -end; +%fix so that linked images slices are plotted +nos = SET(no).Linked; +%nos(nos==no)=[]; %remove the current panel. EH: why? +panelstodo=find(ismember(DATA.ViewPanels,nos)); +for loop=1:length(panelstodo) + panel = panelstodo(loop); + switch DATA.ViewPanelsType{panel} + case {'montage','montagerow','montagefit','montagesegmented'} + DATA.Handles.selectedslice(panel).XData = x; + DATA.Handles.selectedslice(panel).YData = y; + DATA.Handles.selectedslice(panel).LineStyle = '--'; + DATA.Handles.selectedslice(panel).Visible = 'on'; + end +end -%---------------------------------------- -function updateannotationpoints(no,panel) -%---------------------------------------- -%Update coordinates of annotation point handles +%---------------------------- +function drawviability(panel) %#ok +%---------------------------- +%Function to draw viability contour on screen used from drawimageslice, +%drawimagemontage global DATA SET -if nargin < 2 - panel = find(DATA.ViewPanels == no); +hidecell={'hidescar'}; +stateandicon = viewfunctions('iconson',hidecell); +state=[stateandicon{:,1}]; +if state(1) + return end -if not(isempty(SET(no).Point)) - if ~isempty(SET(no).Point.Z) - ind = (round(SET(no).Point.Z)==SET(no).CurrentSlice)&... - (isnan(SET(no).Point.T)|(SET(no).Point.T==SET(no).CurrentTimeFrame)); - pos = find(ind); - for loop=1:length(pos) - set([... - cellref(DATA.Handles.pointo(panel),pos(loop)) ... - cellref(DATA.Handles.pointp(panel),pos(loop))],... - 'xdata',SET(no).Point.Y(pos(loop)),... - 'ydata',SET(no).Point.X(pos(loop))); - set(cellref(DATA.Handles.pointtext(panel),pos(loop)),... - 'position',.... - [SET(no).Point.Y(pos(loop))+2 SET(no).Point.X(pos(loop)) 0]); - end; - if any(~ind) - set([... - cellref(DATA.Handles.pointo(panel),~ind) ... - cellref(DATA.Handles.pointp(panel),~ind)], ... - 'XData',nan,'YData',nan); - set(cellref(DATA.Handles.pointtext(panel),~ind), ... - 'Position',[nan nan]); - end - end; - - -end; - -%----------------------------------- -function drawmontagepoints(no,panel) -%----------------------------------- -%Initiate handles and draw annotation points for montage view. -global DATA SET +type = DATA.ViewPanelsType{panel}; +scale = viewfunctions('getscale',panel); -if not(isempty(SET(no).Point)) - DATA.Handles.pointp{panel} = zeros(1,length(SET(no).Point.X)); - DATA.Handles.pointo{panel} = DATA.Handles.pointp{panel}; - DATA.Handles.pointtext{panel} = DATA.Handles.pointp{panel}; - for loop=1:length(SET(no).Point.X) - [offsety,offsetx] = calcfunctions('calcoffset',... - SET(no).Point.Z(loop),[],no,panel(1)); - DATA.Handles.pointp{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - offsetx+SET(no).Point.Y(loop),offsety+SET(no).Point.X(loop),'w+'); - DATA.Handles.pointo{panel}(loop) = plot(DATA.Handles.imageaxes(panel),... - offsetx+SET(no).Point.Y(loop),offsety+SET(no).Point.X(loop),'wo'); - DATA.Handles.pointtext{panel}(loop) = text(... - 'parent',DATA.Handles.imageaxes(panel),... - 'position',[offsetx+SET(no).Point.Y(loop)+2 offsety+SET(no).Point.X(loop)],... - 'string',SET(no).Point.Label{loop}); - if isnan(SET(no).Point.T(loop)) - set(DATA.Handles.pointtext{panel}(loop),'fontweight','bold') - end; - hide = false; - if (SET(no).Point.T(loop)~=SET(no).CurrentTimeFrame)&¬(isnan(SET(no).Point.T(loop))) - hide = true; - end; - if hide - set([DATA.Handles.pointp{panel}(loop) DATA.Handles.pointo{panel}(loop)], ... - 'XData',nan,'YData',nan); - set(DATA.Handles.pointtext{panel}(loop),'Position',[nan nan]); - end; - end; - set(DATA.Handles.pointtext{panel},'Color',[1 1 1]); - set([... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel}],'ButtonDownFcn',... - sprintf('%s(''pointat_Buttondown'',%d)','annotationpoint',panel)); - -else - DATA.Handles.pointp{panel} = []; - DATA.Handles.pointo{panel} = []; - DATA.Handles.pointtext{panel} = []; -end; - -%------------------------------------- -function updatemontagepoints(no,panel) -%------------------------------------- -%Update coordinates of annotation point handles for montage view. -global DATA SET +no = DATA.ViewPanels(panel); +%Get mask +switch type + case {'montage','montagerow','montagefit','sax3'} + result = viewfunctions('reshape2layout',SET(no).Scar.Result,panel); + case {'one','orth'} + result = SET(no).Scar.Result(:,:,SET(no).CurrentSlice); + otherwise + myfailed('Unknown viewtype in drawviabilityhelper.'); +end -if nargin < 2 - panel = find(DATA.ViewPanels == no); +if sum(result(:))>0 + + %Normal scar outline + scarim = imresize(double(result),scale,'bilinear'); + DATA.Handles.scarcontour(panel).ZData = scarim; + DATA.Handles.scarcontour(panel).Visible = 'on'; + %Fix for interpolated + updatexydata('scarcontour',panel,size(scarim)) + %Weighted scar outline + if SET(no).Scar.UseWeighting + + weighting = viability('viabilityweight',no); %This is a vector with weight and position as corresponding pixels in the whole volume. + + if ~isempty(weighting) + %Get weighting + temp = zeros(size(SET(no).Scar.Result)); + + temp(SET(no).Scar.Result) = weighting; + temp(SET(no).Scar.NoReflow) = 1; %Make sure MO is always included weighted graphically. + + %Sort the weighting + sortedweighting = sort(weighting); + weighted = sum(weighting(:)); %Calculate weighted percentage + total = sum(SET(no).Scar.Result(:)); + f = weighted/total; + + %Find threshold so that it would include f% of the area + f = 1-f; %Since we want the pixelse that are larger than the threshold + thres = sortedweighting(min(max(round(length(sortedweighting)*f),1),length(sortedweighting))); + + %Convert to right size + switch type + case {'montage','montagerow','montagefit','sax3'} + weighting = viewfunctions('reshape2layout',temp,panel); + case {'one','orth'} + weighting = temp(:,:,SET(no).CurrentSlice); + otherwise + myfailed('Unknown viewtype in drawviabilityhelper.'); + end + if max(weighting(:)) < thres + %no pink region to show + DATA.Handles.weightedscarcontour(panel).ZData = []; + DATA.Handles.weightedscarcontour(panel).XData = []; + DATA.Handles.weightedscarcontour(panel).YData = []; + DATA.Handles.weightedscarcontour(panel).Visible = 'off'; + else + weightedscarim = imresize(weighting,scale,'bilinear'); + DATA.Handles.weightedscarcontour(panel).ZData = weightedscarim; + DATA.Handles.weightedscarcontour(panel).Visible = 'on'; + DATA.Handles.weightedscarcontour(panel).LevelList = [thres thres]; + %Fix for interpolated + updatexydata('weightedscarcontour',panel,size(weightedscarim)); + end + else + DATA.Handles.weightedscarcontour(panel).ZData = []; + DATA.Handles.weightedscarcontour(panel).XData = []; + DATA.Handles.weightedscarcontour(panel).YData = []; + DATA.Handles.weightedscarcontour(panel).Visible = 'off'; + end %nonempty weighting + else + DATA.Handles.weightedscarcontour(panel).ZData = []; + DATA.Handles.weightedscarcontour(panel).XData = []; + DATA.Handles.weightedscarcontour(panel).YData = []; + DATA.Handles.weightedscarcontour(panel).Visible = 'off'; + end %use weighting end -oh = cat(1,DATA.Handles.pointo{panel}); -ph = cat(1,DATA.Handles.pointp{panel}); -if not(isempty(SET(no).Point)) - if ~isempty(SET(no).Point.Z) - ind = (SET(no).Point.T==SET(no).CurrentTimeFrame)|isnan(SET(no).Point.T); - pos = find(ind); - for loop=1:length(pos) - [xofs,yofs] = calcfunctions('calcoffset',... - SET(no).Point.Z(pos(loop)),[],no,panel(1)); - set([... - oh(:,pos(loop)) ... - ph(:,pos(loop))],... - 'xdata',yofs+SET(no).Point.Y(pos(loop)),... - 'ydata',xofs+SET(no).Point.X(pos(loop))); - set(cellref(DATA.Handles.pointtext(panel),pos(loop)),... - 'position',.... - [SET(no).Point.Y(pos(loop))+2+yofs SET(no).Point.X(pos(loop))+xofs 0]); - end; - if any(~ind) - set([oh(:,~ind) ph(:,~ind)], 'XData',nan,'YData',nan); - set(cellref(DATA.Handles.pointtext(panel),~ind),'Position',[nan nan]); +%Update taken mocontour and moextentcontour graphically +if sum(SET(no).Scar.NoReflow(:))>0 + + if ~isfield(SET(no).Scar,'MOThreshold') + SET(no).Scar.MOThreshold = 1.5; + end + + %Extract and convert to right size + %Take image and mask with no reflow. + doit = true; + + switch type%DATA.ViewPanelsType{panel} + case {'montage','montagerow','montagefit','sax3'} + contourim = SET(no).Scar.IM; + contourim(~SET(no).Scar.NoReflow) = 1; %Mask with no reflow. 1 is max. + contourim = viewfunctions('reshape2layout',contourim,panel,NaN); %NaN is outsideelement. + case {'one','orth'} + if existfunctions('anyall',SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice)) + contourim = SET(no).Scar.IM(:,:,SET(no).CurrentSlice); + contourim(~SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice)) = 1; %1 is max + else + doit = false; + end + otherwise + myfailed('Unknown viewtype in drawviabilityhelper.'); + end + + if (not(isequal(length(SET(no).Scar.mthreshold),SET(no).ZSize)||isequal(length(SET(no).Scar.mthreshold),1)))&& doit + %Length is not correct. + viability('viabilitycalc'); %this will updat the size correctly. + end + + if doit + %If we need to do, then doit. + + %--- Find suitable threshold + + if isequal(SET(no).Scar.mthreshold,0) + %Manual mode + mthreshold = 1; + logslice = SET(no).Scar.Result(:,:,SET(no).CurrentSlice); + logslice = logslice & (~SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice)); + if sum(logslice(:))>0 + im = SET(no).Scar.IM(:,:,SET(no).CurrentSlice); + mthreshold = min(im(logslice(:))); + if mthreshold<0.01 + mthreshold=0.01; end - end; + end + else + %Some automated mode + mthreshold = SET(no).Scar.mthreshold; + end -end; + %Use remote intensity to calculate good threshold + if length(mthreshold)<2 + thres = mthreshold; + else + thres = mthreshold(SET(no).CurrentSlice); + end + thres = thres*SET(no).Scar.MOThreshold; %OBS if you change here, you need ALSO to change in viabilitycalcvolume. + mocoim = imresize(contourim,scale,'bilinear'); + DATA.Handles.mocontour(panel).ZData = mocoim; + DATA.Handles.mocontour(panel).Visible = 'on'; + DATA.Handles.mocontour(panel).LevelList = [thres thres]; + DATA.Handles.moextentcontour(panel).ZData = imresize(contourim,scale,'bilinear'); + DATA.Handles.moextentcontour(panel).Visible = 'on'; + %Fix for interpolated + szim = size(mocoim); + updatexydata('mocontour',panel,szim); + updatexydata('moextentcontour',panel,szim); + end +end + +%---------------------- +function drawmar(panel) %#ok +%---------------------- +%Function to draw MaR contour on screeen used from drawimageslice, +%drawimagemontage -%---------------------------------------------- -function drawmontageimagetypetext(no,pno,panel) -%---------------------------------------------- -%Initiate handles and draw image type text global DATA SET +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); -DATA.Handles.imagetypetext(panel) = text(... - size(DATA.ViewIM{panel},2)*0.8,... - size(DATA.ViewIM{panel},1)*0.95,... - strcat(SET(pno).ImageType,',',SET(pno).ImageViewPlane),... - 'interpreter','none',... - 'parent',DATA.Handles.imageaxes(panel)); - -%seriesdesciption -DATA.Handles.seriesdescriptiontext(panel) = text(... - size(DATA.ViewIM{panel},2)*0.8,... - size(DATA.ViewIM{panel},1)*0.95,... - SET(pno).SeriesDescription,... - 'interpreter','none',... - 'parent',DATA.Handles.imageaxes(panel)); - -%dicomimagetypetext -DATA.Handles.dicomimagetypetext(panel) = text(... - size(DATA.ViewIM{panel},2)*0.8,... - size(DATA.ViewIM{panel},1)*0.95,... - SET(pno).DICOMImageType,... - 'interpreter','none',... - 'parent',DATA.Handles.imageaxes(panel)); - -%slicetimetext -if isnan(SET(no).TimeVector(SET(no).CurrentTimeFrame)) - stri=''; -else - stri = dprintf('Time:%03d ms',round(1000*SET(no).TimeVector(SET(no).CurrentTimeFrame))); -end +%Get mask +switch DATA.ViewPanelsType{panel} + case {'montage','montagerow','montagefit','sax3'} + result = viewfunctions('reshape2layout',squeeze(SET(no).MaR.Result(:,:,SET(no).CurrentTimeFrame,:)),panel); + case {'one','orth'} + result = SET(no).MaR.Result(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + otherwise + myfailed('Unknown viewtype in mar-drawhelper.'); +end +%Normal MaR outline +%Contour rendering not triggered for constant Zdata +if all(result(:) == 0) + result(1)=1; +end +marimg = imresize(double(result),scale,'bilinear'); +DATA.Handles.marcontour(panel).ZData = marimg; +updatexydata('marcontour',panel,size(marimg)); +stateandicon = viewfunctions('iconson','hidemar'); +if ~stateandicon{1} + DATA.Handles.marcontour(panel).Visible = 'on'; +end +DATA.Handles.marcontour(panel).LevelList = [0.5 0.5]; -DATA.Handles.slicetimetext(panel) = text(... - size(DATA.ViewIM{panel},2)*0.8,... - size(DATA.ViewIM{panel},1)*0.95,... - stri,... - 'interpreter','none',... - 'parent',DATA.Handles.imageaxes(panel)); - - - -% Z cooridnate image text - -% if (strcmp(DATA.CurrentTheme,'3dp')) -% if any(strcmp(DATA.ViewPanelsType{panel},'sag3DP')); -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% -% DATA.Handles.slicecoordtext(panel) = text(... -% size(DATA.ViewIM{panel},2)*0.8,... -% size(DATA.ViewIM{panel},1)*0.95,... -% striZ,... -% 'interpreter','none',... -% 'parent',DATA.Handles.imageaxes(panel)); -% -% -% elseif any(strcmp(DATA.ViewPanelsType{panel},'trans3DP')); -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% -% DATA.Handles.slicecoordtext(panel) = text(... -% size(DATA.ViewIM{panel},2)*0.8,... -% size(DATA.ViewIM{panel},1)*0.95,... -% striZ,... -% 'interpreter','none',... -% 'parent',DATA.Handles.imageaxes(panel)); -% -% elseif any(strcmp(DATA.ViewPanelsType{panel},'cor3DP')); -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% -% DATA.Handles.slicecoordtext(panel) = text(... -% size(DATA.ViewIM{panel},2)*0.8,... -% size(DATA.ViewIM{panel},1)*0.95,... -% striZ,... -% 'interpreter','none',... -% 'parent',DATA.Handles.imageaxes(panel)); -% -% elseif any(strcmp(DATA.ViewPanelsType{panel},'speedim')); -% striZ = dprintf('Z:%.3f',SET(no).CurrentSlice*((SET(no).SliceThickness+SET(no).SliceGap))); -% -% DATA.Handles.slicecoordtext(panel) = text(... -% size(DATA.ViewIM{panel},2)*0.8,... -% size(DATA.ViewIM{panel},1)*0.95,... -% striZ,... -% 'interpreter','none',... -% 'parent',DATA.Handles.imageaxes(panel)); -% -% end -% end +%------------------------------ +function drawcentercross(panel) %#ok +%------------------------------ +global SET DATA +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); +slices = viewfunctions('slicesinpanel',panel); +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},slices-slices(1)+1); +DATA.Handles.centercross(panel).XData = scale*(SET(no).CenterY +(yl-1)*SET(no).YSize); +DATA.Handles.centercross(panel).YData = scale*(SET(no).CenterX +(xl-1)*SET(no).XSize); - -viewupdatetextposition(panel); +%------------------------------ +function drawno(no, isonlyannotation) %#ok +%------------------------------ +%This function is intended to be used after calls that alter a no and may +%effect multiple panels and linked images. This will be used in all +%callbacks altering contours and rois for now. If more speed is needed then we will +%need to write specific calls to draw functions at each callback. +global DATA SET NO -%--------------------------- -function drawcolorbar(panel) -%--------------------------- -%Draw color bar in an image panel -global DATA SET -if nargin < 1 - panel = DATA.CurrentPanel; +if DATA.Silent + return end -%Clean up -try - delete(DATA.Handles.colorbar(panel)); -catch %#ok +if nargin < 1 + no = NO; end -if not(DATA.GUISettings.ShowColorbar) % strcmp(get(DATA.Handles.colorbaricon,'state'),'off') - DATA.Handles.colorbar(panel) = nan; -% for textloop = 1:length(DATA.Handles.colorbartexth), delete(DATA.Handles.colorbartexth(panel,textloop)); end - return +if nargin < 2 + isonlyannotation = false; end -no = DATA.ViewPanels(panel); -parenth = DATA.Handles.imageaxes(panel); -hold(parenth,'on'); -% slice = SET(no).CurrentSlice; -% cmap = flipud(SET(no).Colormap); -% if isempty(cmap) -% cmap = flipud(colormap('gray')); -% end -% im = cat(3,cmap(:,1),cmap(:,2),cmap(:,3)); - -%Use remapuint8 -[window,level] = calcfunctions('con2win',... - SET(no).IntensityMapping.Contrast,... - SET(no).IntensityMapping.Brightness,no); -barminmax = [level-window/2 level+window/2]; -% imminmax = [0 256]; -% im = linspace(imminmax(2),imminmax(1),DATA.GUISettings.ColorMapSize)'; -% if isa(SET(no).IM,'single') -% imcur = SET(no).IM(:,:,SET(no).CurrentTimeFrame,slice); -% barminmax = quantile(imcur(:),[0.1 0.9]); -% im = calcfunctions('remapuint8',linspace( ... -% barminmax(2),barminmax(1),DATA.GUISettings.ColorMapSize)'); -% else -% imcur = single(SET(no).IM(:,:,SET(no).CurrentTimeFrame,slice)); -% barminmax = [0 quantile(imcur(:),0.9)]; -% im = linspace(barminmax(2),barminmax(1),DATA.GUISettings.ColorMapSize)'; -% end +%get all panels which dont have no in it or are linked these are the ones +%that possible have intersections with the updated no and therefore needs +%updating. +panelstodo = find(~ismember(DATA.ViewPanels,SET(no).Linked) & DATA.ViewPanels>0); +panelslinked = find(ismember(DATA.ViewPanels,SET(no).Linked)); -tempmap = SET(no).Colormap; -if isempty(tempmap) - %no colormap set, then it is grey - n = DATA.GUISettings.ColorMapSize; - tempmap = gray(n); +%Then we udpate intersections in intersecting panels +for p = panelstodo + drawintersections(p) end -ax = axis(parenth); -remapcolormap = flipud(reshape(tempmap,[size(tempmap,1) 1 3])); -DATA.Handles.colorbar(panel) = image(ax(2)+[0 (ax(2)-ax(1))/50 ],ax(3:4),remapcolormap,... - 'parent',parenth); - -minmax = barminmax; %calcfunctions('calctruedata',barminmax,no); -rvec = [10 20 50 100 200 500 1000]; -for r = rvec; - scalevec = r*round(minmax(2)/r):-r:minmax(1); - if length(scalevec) <= 12 - break +%update altered panels fully +for p = panelslinked + if strcmp(DATA.ViewPanelsType{p},'one') || strcmp(DATA.ViewPanelsType{p},'orth') + DATA.ViewIM{p} = []; + end + viewfunctions('updatedrawlist',p,isonlyannotation) + drawpanel(p) + if isonlyannotation + % add "drawimage" again, since it was skipped + viewfunctions('addtodrawlist',p,sprintf('drawfunctions(''drawimages'',%d)',p)); + end + if isempty(DATA.ViewIM{p}) + createfunctions('createviewim',p); end end -scalevec = num2cell(scalevec); -strifun = @(x)sprintf('%0.0f',x); -scalevec = cellfun(strifun,scalevec,'UniformOutput',false); -tickvec = linspace(ax(3),ax(4),numel(scalevec)); -% DATA.Handles.colorbarlines = -set(parenth,... - 'ytick',tickvec,... - 'ycolor','w','yaxislocation','right','visible','on','YTickLabel',''); -% DATA.Handles.colorbartexth(panel,:) -texth = zeros(numel(tickvec),1); -for i = 1:numel(tickvec) -% DATA.Handles.colorbartexth(panel,i) - texth(i) = text(ax(2)-3,tickvec(i),scalevec{i}); -end -% set(DATA.Handles.colorbartexth,'Color','w','HorizontalAlignment','right'); -set(texth,'Color','w','HorizontalAlignment','right'); -%------------------------------------- -function drawviabilityhelper(no,panel) -%------------------------------------- -%Function to draw viability contour on screeen used from drawimageslice, -%drawimagemontage +%if montage then we should update the selected slice. +if any(strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},{'montage','montagesegmented','montagerow'})) + drawselectedslice(DATA.CurrentPanel) +end -global DATA SET +%------------------------------ +function drawpoint3D(panel) %#ok +%------------------------------ +global DATA NO +%this draws and updates the panel image intersections. +drawfunctions('drawplaneintersections') -%Get mask -switch DATA.ViewPanelsType{panel} - case {'montage','montagerow','montagefit','sax3'} - result = segment('reshape2layout',SET(no).Scar.Result,no,panel); - case {'one','ortho'} - result = SET(no).Scar.Result(:,:,SET(no).CurrentSlice); +if nargin == 1 + % add points to all panels + scale = viewfunctions('getscale',panel); + switch DATA.ViewPanelsType{panel} + case 'hla' + [y,z,x] = segment('getclickedcoords'); + DATA.Handles.point3D(panel).XData(end+1) = scale*y; + DATA.Handles.point3D(panel).YData(end+1) = scale*z; + case 'vla' + [x,z,y] = segment('getclickedcoords'); + DATA.Handles.point3D(panel).XData(end+1) = scale*x; + DATA.Handles.point3D(panel).YData(end+1) = scale*z; + case 'gla' + [ytemp,xtemp] = segment('getclickedcoords'); + [x,y,z] = calcfunctions('gla2sax',xtemp,ytemp,NO); + [xo,yo] = calcfunctions('sax2gla',x,y,z,NO); + DATA.Handles.point3D(panel).XData(end+1) = scale*xo; + DATA.Handles.point3D(panel).YData(end+1) = scale*yo; + case {'one','orth'} + [y,x,z] = segment('getclickedcoords'); + DATA.Handles.point3D(panel).XData(end+1) = y; + DATA.Handles.point3D(panel).YData(end+1) = x; + x = x/scale; + y = y/scale; + case {'montage'} + [y,x,z] = segment('getclickedcoords'); + [xofs,yofs] = calcfunctions('calcoffset',z,[],NO); + DATA.Handles.point3D(panel).XData(end+1) = scale*(y+yofs); + DATA.Handles.point3D(panel).YData(end+1) = scale*(x+xofs); + case {'montagerow'} + [y,x,z] = segment('getclickedcoords'); + [xofs,yofs] = calcfunctions('calcoffset',z,[],NO); + DATA.Handles.point3D(panel).XData(end+1) = scale*(y+xofs); + DATA.Handles.point3D(panel).YData(end+1) = scale*(x+yofs); otherwise - myfailed('Unknown viewtype in drawviabilityhelper.'); -end; - -if sum(result(:))>0 - - %Ensure that we delete stuff - set(DATA.Handles.imageaxes(panel),'NextPlot','add'); - - %Normal scar outline - [~,DATA.Handles.scarcontour{panel}] = contour(DATA.Handles.imageaxes(panel),double(result),[0.5 0.5]); - if DATA.Pref.BlackWhite - set(DATA.Handles.scarcontour{panel},'linecolor',[1 1 1]); - else - set(DATA.Handles.scarcontour{panel},'linecolor',[1 1 0]); - end; - if DATA.Pref.LineWidth>0 - set(DATA.Handles.scarcontour{panel},'linewidth',DATA.Pref.LineWidth); - else - set(DATA.Handles.scarcontour{panel},'visible','off'); - end; + [y,x,z] = segment('getclickedcoords'); + [xofs,yofs] = calcfunctions('calcoffset',z,[],NO); + DATA.Handles.point3D(panel).XData(end+1) = scale*(y+yofs); + DATA.Handles.point3D(panel).YData(end+1) = scale*(x+xofs); + end + pos = calcfunctions('xyz2rlapfh',NO,x,y,z); + for panel = find(DATA.ViewPanels ~= NO & DATA.ViewPanels > 0) + no = DATA.ViewPanels(panel); + scale = viewfunctions('getscale',panel); + xyz = calcfunctions('rlapfh2xyz',no,pos(:,1),pos(:,2),pos(:,3)); + switch DATA.ViewPanelsType{panel} + case {'one','orth'} + newx = scale*xyz(2,:); + newy = scale*xyz(1,:); + case {'montage'} + [xofs,yofs] = calcfunctions('calcoffset',xyz(3,:),[],no, panel); + newx = scale*(xyz(2,:))+yofs; + newy = scale*(xyz(1,:))+xofs; + otherwise + [xofs,yofs] = calcfunctions('calcoffset',xyz(3,:),[],no, panel); + newx = scale*(xyz(2,:)+yofs); + newy = scale*(xyz(1,:)+xofs); + end - %Weighted scar outline - if SET(no).Scar.UseWeighting - - weighting = viability('viabilityweight',no); %This is a vector with weight and position as corresponding pixels in the whole volume. - - if ~isempty(weighting) - %Get weighting - temp = zeros(size(SET(no).Scar.Result)); - - temp(SET(no).Scar.Result) = weighting; - temp(SET(no).Scar.NoReflow) = 1; %Make sure MO is always included weighted graphically. - - %Sort the weighting - sortedweighting = sort(weighting); - weighted = sum(weighting(:)); %Calculate weighted percentage - total = sum(SET(no).Scar.Result(:)); - f = weighted/total; - %disp(sprintf('noweight:%0.5g weight:%0.5g',sum(result(:)),sum(weighting(:)))); - - %Find threshold so that it would include f% of the area - f = 1-f; %Since we want the pixelse that are larger than the threshold - thres = sortedweighting(min(max(round(length(sortedweighting)*f),1),length(sortedweighting))); - - %Convert to right size - switch DATA.ViewPanelsType{panel} - case {'montage','montagerow','montagefit','sax3'} - weighting = segment('reshape2layout',temp,no,panel); - case {'one','ortho'} - weighting = temp(:,:,SET(no).CurrentSlice); - otherwise - myfailed('Unknown viewtype in drawviabilityhelper.'); - end; - - [~,DATA.Handles.weightedscarcontour{panel}] = contour(DATA.Handles.imageaxes(panel),weighting,[thres thres]); - if DATA.Pref.BlackWhite - set(DATA.Handles.weightedscarcontour{panel},'linecolor',[1 1 1]); - else - set(DATA.Handles.weightedscarcontour{panel},'linecolor',[1 0.5 0.5]); - end; - if DATA.Pref.LineWidth>0 - set(DATA.Handles.weightedscarcontour{panel},'linewidth',DATA.Pref.LineWidth); - else - set(DATA.Handles.weightedscarcontour{panel},'visible','off'); - end; - else - DATA.Handles.weightedscarcontour{panel} = []; - end; %nonempty weighting - else - DATA.Handles.weightedscarcontour{panel} = []; - end %use weighting + DATA.Handles.point3D(panel).XData(end+1) = newx;%scale*xyz(2,:); + DATA.Handles.point3D(panel).YData(end+1) = newy;%scale*xyz(1,:); + end else - %No scar to display - DATA.Handles.scarcontour{panel} = []; - DATA.Handles.weightedscarcontour{panel} = []; -end; + % delete all points be setting all values to nana + for panel = find(DATA.ViewPanels > 0) + DATA.Handles.point3D(panel).XData(:) = nan; + DATA.Handles.point3D(panel).YData(:) = nan; + end + +end -%Update taken mocontour and moextentcontour graphically -if sum(SET(no).Scar.NoReflow(:))>0 - - if ~isfield(SET(no).Scar,'MOThreshold') - SET(no).Scar.MOThreshold = 1.5; - end; +%------------------------------ +function drawpoint(panel) %#ok +%------------------------------ +global DATA SET + +no = DATA.ViewPanels(panel); + +%clear all text. +if ~DATA.Run + set(DATA.Handles.pointtext(panel,:),'Position', [nan nan]); + textoffset = DATA.Handles.point(panel).MarkerSize/2; +end + +if not(isempty(SET(no).Point)) + + if DATA.Pref.BackgroundColor + bgcolor = 'k'; + else + bgcolor = 'none'; + end + %check if placed in 3dp view then we need to draw x and y in a different + %way + + if any(strcmp(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','speedim','cor3DP'})) + + if DATA.Handles.configiconholder.findindented('showpoint') + [r,g,b] = segment3dp.tools('xyz2rgb',SET(no).Point.X,SET(no).Point.Y,SET(no).Point.Z); + switch DATA.ViewPanelsType{panel} + case 'trans3DP' + [~,~,pointstodo] = findfunctions('closestpoint3dp',panel,1,1,SET(no).LevelSet.View.RSlice); + x = g(pointstodo); + y = b(pointstodo); + case 'sag3DP' + [~,~,pointstodo] = findfunctions('closestpoint3dp',panel,1,1,SET(no).LevelSet.View.GSlice); + x = b(pointstodo); + y = r(pointstodo); + case 'cor3DP' + [~,~,pointstodo] = findfunctions('closestpoint3dp',panel,1,1,SET(no).LevelSet.View.BSlice); + x = g(pointstodo); + y = r(pointstodo); + otherwise + pointstodo = []; + x = nan; + y = nan; + end + else + pointstodo = []; + x = []; + y = []; + end - %Extract and convert to right size - %Take image and mask with no reflow. - doit = true; + else + %Normal + slices = viewfunctions('slicesinpanel',panel); + scale = viewfunctions('getscale',panel); - switch DATA.ViewPanelsType{panel} - case {'montage','montagerow','montagefit','sax3'} - contourim = SET(no).Scar.IM; - contourim(~SET(no).Scar.NoReflow) = 1; %Mask with no reflow. 1 is max. - contourim = segment('reshape2layout',contourim,no,panel,NaN); %NaN is outsideelement. - case {'one','ortho'} - if existfunctions('anyall',SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice)) - contourim = SET(no).Scar.IM(:,:,SET(no).CurrentSlice); - contourim(~SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice)) = 1; %1 is max - else - doit = false; - end; - otherwise - myfailed('Unknown viewtype in drawviabilityhelper.'); - end; + %this is the montageindex of the + pointstodo = find(ismember(SET(no).Point.Z,slices)&... + (ismember(SET(no).Point.T,SET(no).CurrentTimeFrame)|isnan(SET(no).Point.T))); %nan means constant over time - if (not(isequal(length(SET(no).Scar.mthreshold),SET(no).ZSize)||isequal(length(SET(no).Scar.mthreshold),1)))&& doit - %Length is not correct. - viability('viabilitycalc'); %this will updat the size correctly. - end; + [yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},SET(no).Point.Z(pointstodo)-slices(1)+1); - if doit - %If we need to do, then doit. - - %--- Find suitable threshold - - if isequal(SET(no).Scar.mthreshold,0) - %Manual mode - mthreshold = 1; - logslice = SET(no).Scar.Result(:,:,SET(no).CurrentSlice); - logslice = logslice & (~SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice)); - if sum(logslice(:))>0 - im = SET(no).Scar.IM(:,:,SET(no).CurrentSlice); - mthreshold = min(im(logslice(:))); - if mthreshold<0.01 - mthreshold=0.01; - end - end; - else - %Some automated mode - mthreshold = SET(no).Scar.mthreshold; - end; - - %Use remote intensity to calculate good threshold - if length(mthreshold)<2 - thres = mthreshold; - else - thres = mthreshold(SET(no).CurrentSlice); - end - thres = thres*SET(no).Scar.MOThreshold; %OBS if you change here, you need ALSO to change in viabilitycalcvolume. - - hold(DATA.Handles.imageaxes(panel),'on'); - [~,DATA.Handles.mocontour{panel}] = contour(DATA.Handles.imageaxes(panel),... - contourim,... - [thres thres]); - - [~,DATA.Handles.moextentcontour{panel}] = contour(DATA.Handles.imageaxes(panel),... - contourim,... - [0.99 0.99]); - - moh = DATA.Handles.mocontour{panel}; - moextenth = DATA.Handles.moextentcontour{panel}; - - if DATA.Pref.BlackWhite - set(moh,'linecolor',[1 1 1],'linestyle',':'); - set(moextenth,'linecolor',[1 1 1],'linestyle','-'); - else - set(moh,'linecolor',[1 0 0],'linestyle',':'); - set(moextenth,'linecolor',[1 0 0],'linestyle','-'); - end; - if DATA.Pref.LineWidth>0 - set(moh,'linewidth',DATA.Pref.LineWidth); - set(moextenth,'linewidth',DATA.Pref.LineWidth); - else - set(moh,'visible','off'); - set(moextenth,'visible','off'); - end; - else - %No mo in current slice and one view, do nothing - DATA.Handles.mocontour{panel} = []; - DATA.Handles.moextentcontour{panel} = []; - end; + y = scale*(SET(no).Point.X(pointstodo)+(xl-1)*SET(no).XSize); + x = scale*(SET(no).Point.Y(pointstodo)+(yl-1)*SET(no).YSize); + end + + DATA.Handles.point(panel).XData = x; + DATA.Handles.point(panel).YData = y; + if ~DATA.Run + for i = 1:length(x) + DATA.Handles.pointtext(panel,i).Position = [x(i)+textoffset,y(i)]; + DATA.Handles.pointtext(panel,i).String = SET(no).Point.Label(pointstodo(i)); + DATA.Handles.pointtext(panel,i).BackgroundColor = bgcolor; + end + end +end + +%--------------------- +function drawinterp(panel,type) %#ok +%----------------------- +%Draws interpolation points in panel. +global DATA SET + + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); +if nargin == 1 + type = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; +else + type = {type}; +end + +slicestoinclude = viewfunctions('slicesinpanel',panel); + +%when playing we dont want to see interpolation points +if DATA.Run == 1 + slicestoinclude = []; +end + +for i = 1:length(type) + x = nan; + y = nan; + if SET(no).([type{i}(1:end-6),'InterpOngoing']) && ~strcmp(DATA.Handles.([lower(type{i}(1:end-6)),'contour'])(panel).LineStyle, 'none') + updateinterpolationsettings(panel,type{i}) + end + for j = 1:length(slicestoinclude) + if ~isempty(SET(no).([type{i},'X'])) && ~isempty(SET(no).([type{i},'X']){SET(no).CurrentTimeFrame,slicestoinclude(j)}) + [xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},j); + yl = (yl-1)*SET(no).XSize; + xl = (xl-1)*SET(no).YSize; + x = cat(1,x,nan,xl+SET(no).([type{i},'Y']){SET(no).CurrentTimeFrame,slicestoinclude(j)}); + y = cat(1,y,nan,yl+SET(no).([type{i},'X']){SET(no).CurrentTimeFrame,slicestoinclude(j)}); + end + end + DATA.Handles.(lower(type{i}))(panel).XData = scale*x; + DATA.Handles.(lower(type{i}))(panel).YData = scale*y; +end + +%--------------------- +function drawcontours(panel,type) %#ok +%----------------------- +%This function draws contours in the designated panel of the input type. It +%depends on that the naming of the coordinate fields of the new contour is homogenous to the +%classical EndoX EndoY representation. +global DATA SET + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); + +%To reduce code amount we use dynamic calling +if nargin == 1 + type = {'Endo','Epi','RVEndo','RVEpi'}; +else + type = {type}; +end + +slicestoinclude = viewfunctions('slicesinpanel',panel); + +for i = 1:length(type) + x = []; + y = []; + if ~isempty(SET(DATA.ViewPanels(panel)).([type{i},'X'])) + for j = 1:length(slicestoinclude) + [xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},j); + yl = (yl-1)*SET(no).XSize; + xl = (xl-1)*SET(no).YSize; + x = cat(1,x,nan,xl+SET(no).([type{i},'Y'])(:,SET(no).CurrentTimeFrame,slicestoinclude(j))); + y = cat(1,y,nan,yl+SET(no).([type{i},'X'])(:,SET(no).CurrentTimeFrame,slicestoinclude(j))); + end + end + %check if interpolationis ongoing in current NO/stack and adjust + %contours appearance + if ~SET(no).([type{i},'InterpOngoing']) + tools('resetinterpolationcontours',panel,type{i}) + else + updateinterpolationsettings(panel,type{i}) + end + DATA.Handles.([lower(type{i}),'contour'])(panel).XData = scale*x; + DATA.Handles.([lower(type{i}),'contour'])(panel).YData = scale*y; +end + +%--------------------- +function drawintersections(panel) +%----------------------- +global DATA SET +persistent markersize +if nargin < 1 + panels = 1:length(DATA.ViewPanels); else - DATA.Handles.mocontour{panel} = []; - DATA.Handles.moextentcontour{panel} = []; -end; + panels = panel; +end + +for panel = panels + no = DATA.ViewPanels(panel); + if not(no==0) + scale = viewfunctions('getscale',panel); + t = SET(no).CurrentTimeFrame; + [endointersectionx,endointersectiony] = ... + calcfunctions('calcsegmentationintersections',panel,'endo',t,DATA.ViewPanelsType{panel}); + % calcfunctions('calcsegmentationintersections',DATA.ViewPanels(panel),'endo',t,DATA.ViewPanelsType{panel}); + [epiintersectionx,epiintersectiony] = ... + calcfunctions('calcsegmentationintersections',panel,'epi',t,DATA.ViewPanelsType{panel}); + % calcfunctions('calcsegmentationintersections',DATA.ViewPanels(panel),'epi',t,DATA.ViewPanelsType{panel}); + + % + [rvendointersectionx,rvendointersectiony] = ... + calcfunctions('calcsegmentationintersections',panel,'rvendo',t,DATA.ViewPanelsType{panel}); + [rvepiintersectionx,rvepiintersectiony] = ... + calcfunctions('calcsegmentationintersections',panel,'rvepi',t,DATA.ViewPanelsType{panel}); + if isempty(markersize) ||(markersize ~= DATA.Pref.MarkerSize) + markersize = DATA.Pref.MarkerSize; + + set([DATA.Handles.endocontourintersection(panel),... + DATA.Handles.epicontourintersection(panel),... + DATA.Handles.rvendocontourintersection(panel),... + DATA.Handles.rvepicontourintersection(panel)],'markersize',markersize); + end + + DATA.Handles.endocontourintersection(panel).XData = scale*endointersectiony; + DATA.Handles.endocontourintersection(panel).YData = scale*endointersectionx; + DATA.Handles.epicontourintersection(panel).XData = scale*epiintersectiony; + DATA.Handles.epicontourintersection(panel).YData = scale*epiintersectionx; + DATA.Handles.rvendocontourintersection(panel).XData = scale*rvendointersectiony; + DATA.Handles.rvendocontourintersection(panel).YData = scale*rvendointersectionx; + DATA.Handles.rvepicontourintersection(panel).XData = scale*rvepiintersectiony; + DATA.Handles.rvepicontourintersection(panel).YData = scale*rvepiintersectionx; + end +end + + + +% DATA.Handles.endocontourintersection(panel).XData = scale*DATA.endointersectiony{panel}{SET(DATA.ViewPanels(panel)).CurrentTimeFrame}; +% DATA.Handles.endocontourintersection(panel).YData = scale*DATA.endointersectionx{panel}{SET(DATA.ViewPanels(panel)).CurrentTimeFrame}; +% DATA.Handles.epicontourintersection(panel).XData = scale*DATA.epiintersectiony{panel}{SET(DATA.ViewPanels(panel)).CurrentTimeFrame}; +% DATA.Handles.epicontourintersection(panel).YData = scale*DATA.epiintersectionx{panel}{SET(DATA.ViewPanels(panel)).CurrentTimeFrame}; %------------------------------ -function showviabilityedits(no) +function showviabilityedits(panel) %#ok %------------------------------ %Show viability edits on screen as a temporary overlay. -global DATA SET NO - -if nargin==0 - no = NO; -end; +global DATA SET -if isempty(SET(no).Scar) - return; - %viability('viabilityreset_Callback'); -end; +no = DATA.ViewPanels(panel); +hidecell={'hidescar'}; +stateandicon = viewfunctions('iconson',hidecell); +state=[stateandicon{:,1}]; -%Check if menu is enabled -if isequal(get(DATA.Handles.hideoverlayicon,'state'),'on') - manualinteraction = false; -else - manualinteraction = true; -end; +if isempty(SET(no).Scar)|| state(1) + return; + %viability('viabilityreset_Callback'); +end if isequal(get(DATA.Handles.viabilityshowinfarctaswhitemenu,'checked'),'on') - showaswhite = true; + showaswhite = true; else - showaswhite = false; -end; + showaswhite = false; +end if ~isempty(SET(no).Scar.GreyZone.map) && ... - isequal(get(DATA.Handles.viabilityshowgrayzonemenu,'checked'),'on') - showgreyzone = true; - manualinteraction = false; + isequal(get(DATA.Handles.viabilityshowgrayzonemenu,'checked'),'on') + showgreyzone = true; else - showgreyzone = false; + showgreyzone = false; end -%If neither then we can just safely exit. -if not(manualinteraction || showaswhite || showgreyzone) - return; -end; +% %If neither then we can just safely exit. +% if not(showaswhite || showgreyzone) +% return; +% end tempnos=no; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants if not(imissingle) - return; + return; end panelstodo = find(DATA.ViewPanels==no); for panel=panelstodo - - %Determine if it is a RGB image or not. - if not(DATA.Silent) - temp = get(DATA.Handles.imagehandle(panel),'CData'); - if ndims(temp)>2 - isrgbimage = true; - else - isrgbimage = false; - end; - else - isrgbimage=false; - end - - clear temp; - - %Ok lets draw it - switch DATA.ViewPanelsType{panel} - case {'one','mmodespatial','ortho'} - scale=2; - temp = SET(no).IM(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - if showgreyzone - temp = imresize(temp,size(SET(no).Scar.GreyZone.map(:,:,1)),'bilinear'); - end - if isrgbimage %RGB iamge - colmap = SET(no).Colormap; - if isempty(colmap) - colmap = colormap('gray'); - end - tempuint8 = min(uint8(255),uint8(1)+calcfunctions('remapuint8',temp,no,colmap)); - else %Default grayscale image - tempuint8 = min(uint8(255),uint8(1)+calcfunctions('remapuint8',temp)); - tempuint8 = repmat(tempuint8,[1 1 3]); %EH: - end; - clear temp; - sz=size(tempuint8); - scarimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); - tmp = SET(no).Scar.Result(:,:,SET(no).CurrentSlice); - tmp = logical(tmp(:)); - - %Show infarct - if DATA.Pref.LineWidth>0 - if showaswhite - scarimrgb(tmp,:) = uint8(255); - %Greyzone - elseif showgreyzone - greytmp = (SET(no).Scar.GreyZone.map(:,:,SET(no).CurrentSlice) == 1); - coretmp = (SET(no).Scar.GreyZone.map(:,:,SET(no).CurrentSlice) == 2); - scarimrgb(greytmp(:),:) = repmat(uint8([127 127 0]),sum(greytmp(:)),1); - scarimrgb(coretmp(:),:) = repmat(uint8([127 0 0]),sum(coretmp(:)),1); - - - end; - end; - - if not(isfield(SET(no).Scar,'NoReflow')) - SET(no).Scar.NoReflow = SET(no).Scar.Auto; - end; - - if manualinteraction - tmp=SET(no).Scar.Manual(:,:,SET(no).CurrentSlice); - tmp=tmp(:); - scarimrgb((tmp==int8( 1)),2) = uint8(255); - scarimrgb((tmp==int8(-1)),3) = uint8(255); - tmp=SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice); - tmp=tmp(:); - scarimrgb(logical(tmp),1) = uint8(255); - end - scarimrgb=reshape(scarimrgb,[sz(1:2) 3]); %EH: added 3 - - - - case {'montage','montagerow','montagefit','sax3'} - % Convert to 2D and layout - scale=1; - if isrgbimage %RGB iamge - colmap = SET(no).Colormap; - if isempty(colmap) - colmap = colormap('gray'); - end - tempuint8 = calcfunctions('remapuint8',... - segment('reshape2layout',squeeze(SET(no).IM(:,:,SET(no).CurrentTimeFrame,:)),no,panel),... - no,colmap); - else %Default grayscale image - tempuint8 = calcfunctions('remapuint8',... - segment('reshape2layout',squeeze(SET(no).IM(:,:,SET(no).CurrentTimeFrame,:)),no,panel),... - no,calcfunctions('returnmapping',no,true)); - end - tempuint8 = min(uint8(255),uint8(1)+tempuint8); - sz = size(tempuint8); - scarimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); - - tmp = segment('reshape2layout',SET(no).Scar.Result,no,panel);%used to be NO but this may cause error - tmp = logical(tmp(:)); - - %Show infarct - if DATA.Pref.LineWidth>0 - if showaswhite - scarimrgb(tmp,:) = uint8(255); - %Greyzone - elseif showgreyzone - temp = imresize(SET(no).Scar.GreyZone.map,[SET(no).XSize SET(no).YSize],'bilinear'); - greytmp = segment('reshape2layout',temp,no,panel); - gztmp = greytmp(:) == 1; - coretmp = greytmp(:) == 2; - - scarimrgb(coretmp,:) = repmat(uint8([127 0 0]),sum(coretmp),1); - scarimrgb(gztmp(:),:) = repmat(uint8([127 127 0]),sum(gztmp(:)),1); - end; - end; - - if not(isfield(SET(no).Scar,'NoReflow')) - SET(no).Scar.NoReflow = repmat(uint8(1),size(SET(no).Scar.Auto)); - end; - - if manualinteraction - tmp=segment('reshape2layout',SET(no).Scar.Manual,no,panel); - tmp=tmp(:); - scarimrgb((tmp==int8( 1)),2) = uint8(255); - scarimrgb((tmp==int8(-1)),3) = uint8(255); - tmp=segment('reshape2layout',SET(no).Scar.NoReflow,no,panel); - tmp=tmp(:); - scarimrgb(logical(tmp),1) = uint8(255); - end - scarimrgb=reshape(scarimrgb,sz); - end - if not(DATA.Silent) - if DATA.Pref.ViewInterpolated - imxsz = size(scarimrgb,1)*scale; - imysz = size(scarimrgb,2)*scale; - im = imresize(scarimrgb,[imxsz imysz],'bilinear'); - else - im=scarimrgb; + %Ok lets draw it + switch DATA.ViewPanelsType{panel} + case {'one','mmodespatial','orth'} + + temp = SET(no).IM(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + if showgreyzone + temp = imresize(temp,size(SET(no).Scar.GreyZone.map(:,:,1)),'bilinear'); + end + colmap = SET(no).Colormap; + if isempty(colmap) + colmap = colormap('gray'); + end + tempuint8 = min(uint8(255),uint8(1)+calcfunctions('remapuint8',temp,no,colmap)); + + sz=size(tempuint8); + scarimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); + tmp = SET(no).Scar.Result(:,:,SET(no).CurrentSlice); + tmp = logical(tmp(:)); + + %Show infarct + if DATA.Pref.LineWidth>0 + if showaswhite + scarimrgb(tmp,:) = uint8(255); + %Greyzone + elseif showgreyzone + greytmp = (SET(no).Scar.GreyZone.map(:,:,SET(no).CurrentSlice) == 1); + coretmp = (SET(no).Scar.GreyZone.map(:,:,SET(no).CurrentSlice) == 2); + scarimrgb(greytmp(:),:) = repmat(uint8([127 127 0]),sum(greytmp(:)),1); + scarimrgb(coretmp(:),:) = repmat(uint8([127 0 0]),sum(coretmp(:)),1); + end + end + + if not(isfield(SET(no).Scar,'NoReflow')) + SET(no).Scar.NoReflow = SET(no).Scar.Auto; + end + + + tmp=SET(no).Scar.Manual(:,:,SET(no).CurrentSlice); + tmp=tmp(:); + scarimrgb((tmp==int8( 1)),2) = uint8(255); + scarimrgb((tmp==int8(-1)),3) = uint8(255); + tmp=SET(no).Scar.NoReflow(:,:,SET(no).CurrentSlice); + tmp=tmp(:); + scarimrgb(logical(tmp),1) = uint8(255); + + scarimrgb=reshape(scarimrgb,[sz(1:2) 3]); %EH: added 3 + + case {'montage','montagerow','montagefit','sax3'} + % Convert to 2D and layout + scale=1; + colmap = SET(no).Colormap; + if isempty(colmap) + colmap = colormap('gray'); end - set(DATA.Handles.imagehandle(panel),'CData',im); + tempuint8 = calcfunctions('remapuint8',... + viewfunctions('reshape2layout',squeeze(SET(no).IM(:,:,SET(no).CurrentTimeFrame,:)),panel),... + no,colmap); + + tempuint8 = min(uint8(255),uint8(1)+tempuint8); + sz = size(tempuint8); + scarimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); + + tmp = viewfunctions('reshape2layout',SET(no).Scar.Result,panel);%used to be NO but this may cause error + tmp = logical(tmp(:)); + + %Show infarct + if DATA.Pref.LineWidth>0 + if showaswhite + scarimrgb(tmp,:) = uint8(255); + %Greyzone + elseif showgreyzone + temp = imresize(SET(no).Scar.GreyZone.map,[SET(no).XSize SET(no).YSize],'bilinear'); + greytmp = viewfunctions('reshape2layout',temp,panel); + gztmp = greytmp(:) == 1; + coretmp = greytmp(:) == 2; + + scarimrgb(coretmp,:) = repmat(uint8([127 0 0]),sum(coretmp),1); + scarimrgb(gztmp(:),:) = repmat(uint8([127 127 0]),sum(gztmp(:)),1); + end + end + + if not(isfield(SET(no).Scar,'NoReflow')) + SET(no).Scar.NoReflow = repmat(uint8(1),size(SET(no).Scar.Auto)); end + + + tmp=viewfunctions('reshape2layout',SET(no).Scar.Manual,panel); + tmp=tmp(:); + scarimrgb((tmp==int8( 1)),2) = uint8(255); + scarimrgb((tmp==int8(-1)),3) = uint8(255); + tmp=viewfunctions('reshape2layout',SET(no).Scar.NoReflow,panel); + tmp=tmp(:); + scarimrgb(logical(tmp),1) = uint8(255); + + scarimrgb=reshape(scarimrgb,sz); + end + if not(DATA.Silent) + scale = viewfunctions('getscale',panel); + imxsz = size(scarimrgb,1)*scale; + imysz = size(scarimrgb,2)*scale; + im = imresize(scarimrgb,[imxsz imysz],'bilinear'); + set(DATA.Handles.imagehandles(panel),'CData',im); + end end -%Update menu. Seems unnecessary. -viability('viabilitymenu'); - -%------------------------------- -function drawmarhelper(no,panel) -%------------------------------- -%Function to draw MaR contour on screeen used from drawimageslice, -%drawimagemontage +%-------------------------------- +function draw3dpline(panel,type) %#ok +%-------------------------------- +%Draws stack intersections in 3dp. global DATA SET +no = DATA.ViewPanels(panel); -delete(DATA.Handles.marcontour{panel}); +if DATA.Handles.configiconholder.findindented('showcross') + %Find max size + %[rmax,gmax,bmax] = segment3dp.tools('xyz2rgb',SET(no).XSize,SET(no).YSize,SET(no).ZSize); + %just use 8000 instead never used image that large + + switch type + case 'br' + x = [0, 8000]; + y = [SET(no).LevelSet.View.RSlice SET(no).LevelSet.View.RSlice]; + case 'gr' + x = [0, 8000]; + y = [SET(no).LevelSet.View.RSlice SET(no).LevelSet.View.RSlice]; + case 'gb' + x = [SET(no).LevelSet.View.BSlice SET(no).LevelSet.View.BSlice]; + y = [0, 8000]; + case 'rb' + x = [0, 8000]; + y = [SET(no).LevelSet.View.BSlice SET(no).LevelSet.View.BSlice]; + case 'rg' + x = [SET(no).LevelSet.View.GSlice SET(no).LevelSet.View.GSlice]; + y = [0, 8000]; + case 'bg' + x = [SET(no).LevelSet.View.GSlice SET(no).LevelSet.View.GSlice]; + y = [0, 8000]; + end +else + x = NaN; + y = NaN; +end -%Get mask -switch DATA.ViewPanelsType{panel} - case {'montage','montagerow','montagefit','sax3'} - result = segment('reshape2layout',squeeze(SET(no).MaR.Result(:,:,SET(no).CurrentTimeFrame,:)),no,panel); - case {'one','ortho'} - result = SET(no).MaR.Result(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - otherwise - myfailed('Unknown viewtype in mar-drawhelper.'); -end; +DATA.Handles.([type,'line'])(panel).XData = x; +DATA.Handles.([type,'line'])(panel).YData = y; -if (sum(result(:))>0) - - %Ensure that we delete stuff - set(DATA.Handles.imageaxes(panel),'NextPlot','add'); - - %Normal MaR outline - [c,DATA.Handles.marcontour{panel}] = contour(DATA.Handles.imageaxes(panel),double(result),[0.5 0.5]); - set(DATA.Handles.marcontour{panel},'linecolor',[1 1 1]); - if DATA.Pref.LineWidth>0 - set(DATA.Handles.marcontour{panel},'linewidth',DATA.Pref.LineWidth); - else - set(DATA.Handles.marcontour{panel},'visible','off'); - end; +%-------------------------------- +function displaypoints(view,ima) %#ok +%-------------------------------- +%Draws annotation points in 3dp imageaxes ima according to view. + +global SET DATA NO + +if ~DATA.Handles.configiconholder.findindented('showpoint') + %Hide + delete(DATA.Handles.([view,'text3dp']))%This removes old points else - DATA.Handles.marcontour{panel} = []; -end; + + %add points + [r,g,b] = segment3dp.tools('xyz2rgb',SET(NO).Point.X,SET(NO).Point.Y, SET(NO).Point.Z); + switch view + case 'r' + pointstoplot = round(r)==SET(NO).LevelSet.View.RSlice; + x = g; + y = b; + case 'g' + pointstoplot = round(g)==SET(NO).LevelSet.View.GSlice; + x = b; + y = r; + case 'b' + pointstoplot = round(b)==SET(NO).LevelSet.View.BSlice; + x = g; + y = r; + end + + delete(DATA.Handles.([view,'text3dp']))%This removes old points + + DATA.Handles.([view,'text3dp']) = []; + + if any(pointstoplot) + for loop = find(pointstoplot) + DATA.Handles.([view,'text3dp'])=[DATA.Handles.([view,'text3dp']),text('parent',ima,... + 'position',[x(loop) y(loop)],'HorizontalAlignment','center',... + 'string','+','color',[1,1,1]), text('parent',ima,... + 'position',[x(loop)+5 y(loop)],'HorizontalAlignment','left',... + 'string',SET(NO).Point.Label{loop},'color',[1,1,1])]; + set(DATA.Handles.([view,'text3dp']),'ButtonDownFcn','segment3dp.tools(''delete3dppoints'')'); + end + end +end -%------------------------ -function showmaredits(no) -%------------------------ -%Show MaR edits on screen as a temporary overlay. +%----------------------------------- +function draw3dpoutline(panel,type) %#ok +%------------------------------------ +%Shows contour of 3d segmentation if outline button is indented and motion function isnt running. global DATA SET NO -if nargin==0 - no = NO; -end; +% if speed im we want to use the current selected imagestack for contour. +%if strcmp(type,'s') +% im = double(getimagehelper(SET(NO).LevelSet.BW,SET(NO).LevelSet.Pen.Color)); +%else +% im = double(getimagehelper(SET(NO).LevelSet.BW,type)); +%end -if isempty(SET(no).MaR) - return; -end; +switch DATA.ViewPanelsType{panel} + case 'trans3DP' + im = double(getimagehelper(SET(NO).LevelSet.BW,'r')); + case 'sag3DP' + im = double(getimagehelper(SET(NO).LevelSet.BW,'g')); + case 'cor3DP' + im = double(getimagehelper(SET(NO).LevelSet.BW,'b')); + case 'speedim' + im = double(getimagehelper(SET(NO).LevelSet.BW,SET(NO).LevelSet.Pen.Color)); +end -%Check if menu is enabled -if isequal(get(DATA.Handles.hideoverlayicon,'state'),'on') - manualinteraction = false; -else - manualinteraction = true; -end; +%no segmentation +if sum(im(:)>127)==0 %all(im==0) + DATA.Handles.threedpcontour(panel).ZData = [127 0 ; 0 0]; + return +end -if not(manualinteraction) - return; -end; +DATA.Handles.threedpcontour(panel).ZData = im; +DATA.Handles.threedpcontour(panel).Visible = 'on'; -tempnos=no; -imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants -if not(imissingle) - return; -end +%----------------------------------------- +function im = getimagehelper(vol,view) +%---------------------------------------- +%Similar as getimage, but do assme no TSize as stored locally in BW. -panelstodo = find(DATA.ViewPanels==no); +global DATA SET NO -for panel=panelstodo - - %Determine if it is a RGB image or not. - if not(DATA.Silent) - temp = get(DATA.Handles.imagehandle(panel),'CData'); - if ndims(temp)>2 - isrgbimage = true; - else - isrgbimage = false; - end; - else - isrgbimage=false; - end - if isempty(SET(no).Colormap) - isrgbimage = false; +switch lower(DATA.LevelSet.imageorientation) + case 'transversal' + switch view + case 'r' + im = squeeze(vol(:,:,SET(NO).LevelSet.View.RSlice)); + case 'g' + im = squeeze(vol(:,SET(NO).LevelSet.View.GSlice,:))'; + case 'b' + im = squeeze(vol(SET(NO).LevelSet.View.BSlice,:,:))'; end - - clear temp; - - %Ok lets draw it - switch DATA.ViewPanelsType{panel} - case {'one','mmodespatial','ortho'} - temp = SET(no).IM(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - - if isrgbimage %RGB iamge - tempuint8 = min(uint8(255),uint8(1)+calcfunctions('remapuint8',temp,no,SET(no).Colormap)); - else %Default grayscale image - tempuint8 = min(uint8(255),uint8(1)+calcfunctions('remapuint8',temp)); - tempuint8 = repmat(tempuint8,[1 1 3]); %EH: - end; - clear temp; - sz=size(tempuint8); - marimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); - - tmp=SET(no).MaR.Manual(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - tmp=tmp(:); - marimrgb((tmp==int8( 1)),2) = uint8(255); - marimrgb((tmp==int8(-1)),3) = uint8(255); - marimrgb=reshape(marimrgb,[sz(1:2) 3]); %EH: added 3 - - case {'montage','montagerow','montagefit','sax3'} - % Convert to 2D and layout - - if isrgbimage %RGB iamge - tempuint8 = calcfunctions('remapuint8',... - segment('reshape2layout',squeeze(SET(no).IM(:,:,SET(no).CurrentTimeFrame,:)),no,panel),... - no,SET(no).Colormap); - else %Default grayscale image - tempuint8 = calcfunctions('remapuint8',... - segment('reshape2layout',squeeze(SET(no).IM(:,:,SET(no).CurrentTimeFrame,:)),no,panel),... - no,calcfunctions('returnmapping',no,true)); - end - tempuint8 = min(uint8(255),uint8(1)+tempuint8); - sz = size(tempuint8); - marimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); - - tmp=segment('reshape2layout',SET(no).MaR.Manual(:,:,SET(no).CurrentTimeFrame,:),no,panel); - tmp=tmp(:); - marimrgb((tmp==int8( 1)),2) = uint8(255); - marimrgb((tmp==int8(-1)),3) = uint8(255); - marimrgb=reshape(marimrgb,sz); + case 'sagittal' + switch view + case 'r' + im = squeeze(vol(SET(NO).LevelSet.View.RSlice,:,:)); + case 'g' + im = squeeze(vol(:,:,SET(NO).LevelSet.View.GSlice)); + case 'b' + im = squeeze(vol(:,SET(NO).LevelSet.View.BSlice,:)); end - if not(DATA.Silent) - set(DATA.Handles.imagehandle(panel),'CData',marimrgb); + case 'coronal' + switch view + case 'r' + im = squeeze(vol(SET(NO).LevelSet.View.RSlice,:,:))'; + case 'g' + im = squeeze(vol(:,SET(NO).LevelSet.View.GSlice,:)); + case 'b' + im = squeeze(vol(:,:,SET(NO).LevelSet.View.BSlice)); end end -%--------------------- -function showedits(no) -%--------------------- -%Show edits (overlays) of scar and mar if current mode +%------------------------------ +function im = getimage(view) +%----------------------------- +%Get image for view given imageorientation, r = transversal, g = sagittal, +%b=coronal + global DATA SET NO -if isequal(DATA.CurrentTheme,'scar') || ... - ~isempty(SET(no).Scar) && ~isempty(SET(no).Scar.GreyZone.map) && ... - max(SET(no).Scar.GreyZone.map(:)) > 0 - stateandicon = segment('iconson','hidescarmanual'); - if ~stateandicon{1}%isequal(get(DATA.Handles.hidescaricon,'state'),'off') - showviabilityedits(no); +switch lower(DATA.LevelSet.imageorientation) + case 'transversal' + switch view + case 'r' + im = squeeze(SET(NO).IM(:,:,1,SET(NO).LevelSet.View.RSlice)); + case 'g' + im = squeeze(SET(NO).IM(:,SET(NO).LevelSet.View.GSlice,1,:))'; + case 'b' + im = squeeze(SET(NO).IM(SET(NO).LevelSet.View.BSlice,:,1,:))'; + end + case 'sagittal' + switch view + case 'r' + im = squeeze(SET(NO).IM(SET(NO).LevelSet.View.RSlice,:,1,:)); + case 'g' + im = squeeze(SET(NO).IM(:,:,1,SET(NO).LevelSet.View.GSlice)); + case 'b' + im = squeeze(SET(NO).IM(:,SET(NO).LevelSet.View.BSlice,1,:)); end -elseif isequal(DATA.CurrentTheme,'mar') - stateandicon = segment('iconson','hidescarmanual'); - if ~stateandicon{1}%isequal(get(DATA.Handles.hidemaricon,'state'),'off') - showmaredits(no); + case 'coronal' + switch view + case 'r' + im = squeeze(SET(NO).IM(SET(NO).LevelSet.View.RSlice,:,1,:))'; + case 'g' + im = squeeze(SET(NO).IM(:,SET(NO).LevelSet.View.GSlice,1,:)); + case 'b' + im = squeeze(SET(NO).IM(:,:,1,SET(NO).LevelSet.View.BSlice)); end -% elseif isequal(DATA.CurrentTheme,'3dp') -% drawimagetypetext(NO, no, panel) end -%------------------------------------- -function viewupdatetextposition(panel) -%------------------------------------- -% Updates the location of the corner text, to always stay still. -% From drawx(), it is called panelwise, since the linked panels aren't -% ready when the first panel is drawn. From other situations, it is called -% without arguements, and handles the linkage by itself. /JU +%---------------------------------- +function im = getoverlayimage(view) %#ok +%---------------------------------- +%Get image including overlay, view is either of 'r','g','b'. global DATA SET NO -%Input to force black background around corner text to improve visibility -if DATA.Pref.BackgroundColor - bgcolor = 'blue'; -else - bgcolor = 'none'; -end -myset(DATA.Handles.imagetypetext,'BackgroundColor',bgcolor); %Use myset to handle NaNs in vector -myset(DATA.Handles.seriesdescriptiontext,'BackgroundColor',bgcolor) -myset(DATA.Handles.dicomimagetypetext,'BackgroundColor',bgcolor) -myset(DATA.Handles.slicetimetext,'BackgroundColor',bgcolor) -myset(DATA.Handles.slicecoordtext,'BackgroundColor',bgcolor) -if nargin==1 - ind = panel; -else - no = NO; - nos=SET(no).Linked; - ind = []; - for loop=1:length(nos) - ind = [ind find(DATA.ViewPanels==nos(loop))]; %#ok - end; - ind = unique(ind); %remove duplicates. - ind = ind(~strcmp(DATA.ViewPanelsType(ind),'mmodetemporal')); +im = getimage(view); +bw = getimagehelper(SET(NO).LevelSet.BW,view); +if ~isfield(DATA.LevelSet,'Man') || isempty(DATA.LevelSet.Man) + DATA.LevelSet.Man = repmat(int8(0),size(SET(NO).LevelSet.BW)); end +man = getimagehelper(DATA.LevelSet.Man,view); -if ~any(strcmp(DATA.ProgramName,{'Segment 3DPrint'})) - for panel=ind - xlim=get(DATA.Handles.imageaxes(panel),'xlim'); - ylim=get(DATA.Handles.imageaxes(panel),'ylim'); - - extent = get(DATA.Handles.imagetypetext(panel),'extent'); - set(DATA.Handles.imagetypetext(panel),'color','white','position',... - [xlim(2)-extent(3) ... - ylim(2)-extent(4) 0]); - - extent = get(DATA.Handles.dicomimagetypetext(panel),'extent'); - set(DATA.Handles.dicomimagetypetext(panel),'color','white','position',... - [xlim(2)-extent(3) ... - ylim(2)-2*extent(4) 0]); - - extent = get(DATA.Handles.seriesdescriptiontext(panel),'extent'); - set(DATA.Handles.seriesdescriptiontext(panel),'color','white','position',... - [xlim(2)-extent(3) ... - ylim(2)-3*extent(4) 0]); - - extent = get(DATA.Handles.slicetimetext(panel),'extent'); - set(DATA.Handles.slicetimetext(panel),'color','white','position',... - [xlim(2)-extent(3) ... - ylim(2)-4*extent(4) 0]); - -% extent = get(DATA.Handles.slicecoordtext(panel),'extent'); -% set(DATA.Handles.slicecoordtext(panel),'color','white','position',... -% [xlim(2)-extent(3) ... -% ylim(2)-5*extent(4) 0]); - -% if (strcmp(DATA.CurrentTheme,'3dp')) -% if any(strcmp(DATA.ViewPanelsType,'sag3DP')); -% striZ = dprintf('Z:%.3f',SET(NO).CurrentSlice*((SET(NO).SliceThickness+SET(NO).SliceGap))); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% -% elseif any(strcmp(DATA.ViewPanelsType,'trans3DP')); -% striZ = dprintf('Z:%.3f',SET(NO).CurrentSlice*((SET(NO).SliceThickness+SET(NO).SliceGap))); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% elseif any(strcmp(DATA.ViewPanelsType,'cor3DP')); -% striZ = dprintf('Z:%.3f',SET(NO).CurrentSlice*((SET(NO).SliceThickness+SET(NO).SliceGap))); -% DATA.Handles.slicecoordtext(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-5*extent(4),... -% striZ,'interpreter','none','color','white'); -% end -% end +im = segment3dp.tools('levelsetremapandoverlay',im,bw,man); - end -end -%------------------------------ -function viewupdateannotext(panel) -%------------------------------ -% Updates the visibility of point/measurement text. -% Respects hideX settings. -% -% If point is inbound, pointtext is visible. -% If measurementtext is inbound, measurementtext is visible. -% If whole ROI is inbound, place XXXX -% If only some of ROI is inbound, place at any inbound point -% If whole ROI is outside, make ROItext not visible. +%-------------------------------- +function drawintensitymapping %#ok +%-------------------------------- +%Draws intensity mapping curve and add gray colorbar global DATA SET NO -if nargin==1 - ind = panel; - no = DATA.ViewPanels(panel(1)); -else - no = NO; - nos=SET(no).Linked; - ind = []; - for loop=1:length(nos) - ind = [ind find(DATA.ViewPanels==nos(loop))]; %#ok - end; - ind = unique(ind); %remove duplicates. -end +c = [0 0 0]; -nom = no; -if ~isempty(SET(no).Parent) - nom=SET(no).Parent; -end +offset = SET(NO).LevelSet.IntensityOffset; +slope = SET(NO).LevelSet.IntensitySlope; +[minvalue,maxvalue] = segment3dp.tools('getminmax'); +windowmin = SET(NO).LevelSet.WindowCenter-SET(NO).LevelSet.WindowWidth/2; +windowmax = SET(NO).LevelSet.WindowCenter+SET(NO).LevelSet.WindowWidth/2; -for panel=ind - if ~strcmp(DATA.ViewPanelsType(panel),'mmodetemporal') - xlim=get(DATA.Handles.imageaxes(panel),'xlim'); - ylim=get(DATA.Handles.imageaxes(panel),'ylim'); - - if ~isempty(SET(nom).Point) - for loop=1:length(DATA.Handles.pointo{panel}) - px=get(DATA.Handles.pointo{panel}(loop),'xdata'); - py=get(DATA.Handles.pointo{panel}(loop),'ydata'); - if ~isnan(px) - if (px>xlim(1))&&(py>ylim(1))&&(pxxlim(1))&&(my>ylim(1))&&(mxxlim(1))&(ry>ylim(1))&(rx=0,1,'first'); + x1 = x(ind); + x2 = center; + [~,ind] = find(y>=0,1,'last'); + x3 = x(ind); end -state=stateandicon{13,1}; +%Ensure visible on screen +if x1<(center-width/2) + x1 = center-width/2; +end -if state%strcmp(get(DATA.Handles.hidetexticon,'state'),'on') - myset([DATA.Handles.mocontour{:}],'Visible','off'); - myset([DATA.Handles.moextentcontour{:}],'Visible','off'); %microvascular obstruction contour - myset([DATA.Handles.weightedscarcontour{:}],'Visible','off'); %Weighted scar contour +if x3>(center+width/2) + x3 = center+width/2; end -%-----3D functions------------------------------------ -%------------------------- -function corspeed_view -%------------------------- -%This function initiates the coronal and speed image segment 3DP view -global DATA SET NO -DATA.CurrentPanel=1; -SET(NO).LevelSet.Pen.Color = 'b'; -drawfunctions('drawimageview',[NO NO],[1,2],{'cor3DP','speedim'}); -lineupdate3dp +%Find y-coordinates +y1 = interp1(x,y,x1); +y2 = interp1(x,y,x2); +y3 = interp1(x,y,x3); %------------------------- -function sagspeed_view -%------------------------- -%This function initiates the sagittal and speed image Segment 3DP view -global DATA SET NO -DATA.CurrentPanel = 1; -SET(NO).LevelSet.Pen.Color = 'g'; -drawfunctions('drawimageview',[NO NO],[1,2],{'sag3DP','speedim'}); -lineupdate3dp -%------------------------- -function transspeed_view -%------------------------- -%This function initiates the transversal and speed image Segment 3DP view -global DATA SET NO -DATA.CurrentPanel = 1; -SET(NO).LevelSet.Pen.Color = 'r'; -drawfunctions('drawimageview',[NO NO],[1,2],{'trans3DP','speedim'}); -lineupdate3dp -%------------------------- -function tssc_view +function updatemapping %#ok %------------------------- -%This function initiates the transversal and speed image Segment 3DP view -global DATA SET NO -DATA.CurrentPanel=1; -SET(NO).LevelSet.Pen.Color = 'r'; -%Go to fourpanel view -drawfunctions('drawimageview',[NO NO NO NO],[2,2],{'trans3DP','speedim','sag3DP','cor3DP'}); -%drawimagetypetext3dp(NO,1) -lineupdate3dp -%----------------- -function sdraw -%------------------ -%Draw / initialize the speed part. -global DATA SET NO - -handles = DATA.Handles; -if isempty(DATA.LevelSet.SpeedIM) - updatespeed; -end; - -%--- 2D Speed image -try - im = getimagehelper(DATA.LevelSet.SpeedIM,SET(NO).LevelSet.Pen.Color); - handles.simage = imagesc(im,'parent',handles.speedaxes); -catch %#ok - handles.simage = []; -end; - -[zoomstate,dataaspectratio] = sgetzoomstatehelper; - -d = 7; -if isempty(zoomstate) - zoomstate = [1 size(im,1) 1 size(im,2)]; -end; -handles.stext = text('position',[zoomstate(1)+d/2,zoomstate(3)+d],'string','Object likelihood','parent',handles.speedaxes, 'color', 'w'); %Text - -%Aspect ratio -axis(handles.speedaxes,'off'); -set(handles.speedaxes,'Clim',[-2000 2000],'dataaspectratio',dataaspectratio); - -colormap(handles.speedaxes,DATA.LevelSet.colormap); +%update the mapping graphically -%---------------- -function supdate -%---------------- -%Updates the 3dp speed image view global DATA SET NO -handles = DATA.Handles; -imh=handles.imagehandle(strcmp(DATA.ViewPanelsType,'speedim')); -ima=handles.imageaxes(strcmp(DATA.ViewPanelsType,'speedim')); - -%--- Update 2D 'speed' image - -if isempty(SET(NO).LevelSet.SpeedIM) - segment3dp.tools('updatespeed'); -end; - -tempimage = getimage(SET(NO).LevelSet.Pen.Color); -%temp = segment3dp.tools('getimage',SET(NO).LevelSet.Pen.Color); - -outlinedraw3dp('s') - -%Remap the image -tempremapped = fastremap(tempimage,SET(NO).LevelSet.Speed.IntensityMap,int16(SET(NO).minValue),int16(SET(NO).maxValue)); %Doesnt work with color -tempremapped = single(tempremapped)/4000+0.5; %scale it 0...1 -tempremapped = uint8(tempremapped*255)+1; %scale it to 1..256 +%y = k(x-offset) -%convert colormap to uint8 -cmap = DATA.LevelSet.colormap; -cmap = uint8(255*cmap); -temprgb = cat(2,... - cmap(tempremapped,1),... - cmap(tempremapped,2),... - cmap(tempremapped,3)); +[x,y] = segment3dp.tools('getmappingline',NO); -temp = reshape(temprgb,[size(tempimage,1) size(tempimage,2) 3]); +SET(NO).LevelSet.Speed.IntensityMap = int16(2000*y); -switch DATA.ViewPanelsType{DATA.CurrentPanel} - case 'trans3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','r',NO); - zoomstate = SET(NO).LevelSet.View.RZoomState; - case 'sag3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','g',NO); - zoomstate = SET(NO).LevelSet.View.GZoomState; - case 'cor3DP' - [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres','b',NO); - zoomstate = SET(NO).LevelSet.View.BZoomState; -end +[x1,y1,x2,y2,x3,y3] = getpointcoordinates(NO,x,y); -%Update image -set(imh,'cdata',temp,'xdata',[0.5,ysz-0.5],'ydata',[0.5,xsz-0.5]) -set(ima,...% - 'dataaspectratio',[1/yres 1/xres 1],... - 'xlim',zoomstate(1:2),'ylim',zoomstate(3:4)); +set(DATA.Handles.speedimline,'xdata',x,'ydata',y); +set(DATA.Handles.speedpoint1,'xdata',x1,'ydata',y1); +set(DATA.Handles.speedpoint2,'xdata',x2,'ydata',y2); +set(DATA.Handles.speedpoint3,'xdata',x3,'ydata',y3); -%--------------------- -function supdatemotion %#ok -%--------------------- -%Update speed image, only single slice and from mapping, used by -%speedpointmotion fncs. +%---------------------- +function drawmapping %#ok +%---------------------- +%Prepare the mapping area for drawing global DATA SET NO -%Get the image -tempimage = getimage(SET(NO).LevelSet.Pen.Color); - -%Remap the image -tempremapped = fastremap(tempimage,SET(NO).LevelSet.Speed.IntensityMap,int16(SET(NO).minValue),int16(SET(NO).maxValue)); %Doesnt work with color -tempremapped = single(tempremapped)/4000+0.5; %scale it 0...1 -tempremapped = uint8(tempremapped*255)+1; %scale it to 1..256 - -%convert colormap to uint8 -cmap = DATA.LevelSet.colormap; -cmap = uint8(255*cmap); -temprgb = cat(2,... - cmap(tempremapped,1),... - cmap(tempremapped,2),... - cmap(tempremapped,3)); -temprgb = reshape(temprgb,[size(tempimage,1) size(tempimage,2) 3]); - -%Update image -set(DATA.Handles.imagehandle(strcmp(DATA.ViewPanelsType,'speedim')),'cdata',temprgb) - -%--------------------- -function lineupdate3dp %#ok -%--------------------- -%Updates lines displaying intersections of 3dp imageviews - -global DATA SET NO +fgc = [0 0 0]; +bgc = [0.94 0.94 0.94]; -handles = DATA.Handles; +windowmin = min(SET(NO).LevelSet.WindowCenter-SET(NO).LevelSet.WindowWidth/2,SET(NO).LevelSet.Speed.Center-SET(NO).LevelSet.Speed.Width/2); +windowmax = max(SET(NO).LevelSet.WindowCenter+SET(NO).LevelSet.WindowWidth/2,SET(NO).LevelSet.Speed.Center+SET(NO).LevelSet.Speed.Width/2); -if ~DATA.Handles.configiconholder.findindented('showcross') - if any(strcmp(DATA.ViewPanelsType,'sag3DP')); - set(handles.grline,'visible','off'); - set(handles.gbline,'visible','off'); - end - if any(strcmp(DATA.ViewPanelsType,'trans3DP')); - set(handles.rgline,'visible','off'); - set(handles.rbline,'visible','off'); - end - if any(strcmp(DATA.ViewPanelsType,'cor3DP')); - set(handles.bgline,'visible','off'); - set(handles.brline,'visible','off'); - end - return -end +%Plot mapping +[x,y] = segment3dp.tools('getmappingline',NO); +DATA.Handles.speedimline = plot(DATA.Handles.mappingaxes,x,y,'b-'); +set(DATA.Handles.mappingaxes,'ytick',[-1 0 1],... + 'yticklabel',{'0%' '50%','100%'}); -if any(strcmp(DATA.ViewPanelsType,'sag3DP')); - set(handles.grline,'ydata',[SET(NO).LevelSet.View.RSlice SET(NO).LevelSet.View.RSlice],... - 'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''g'')','visible','on'); - set(handles.gbline,'xdata',[SET(NO).LevelSet.View.BSlice SET(NO).LevelSet.View.BSlice],... - 'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''g'')','visible','on'); -end -if any(strcmp(DATA.ViewPanelsType,'trans3DP')); - set(handles.rgline,'xdata',[SET(NO).LevelSet.View.GSlice SET(NO).LevelSet.View.GSlice],... - 'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''r'')','visible','on'); - set(handles.rbline,'ydata',[SET(NO).LevelSet.View.BSlice SET(NO).LevelSet.View.BSlice],... - 'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''r'')','visible','on'); -end -if any(strcmp(DATA.ViewPanelsType,'cor3DP')); - set(handles.bgline,'xdata',[SET(NO).LevelSet.View.GSlice SET(NO).LevelSet.View.GSlice],... - 'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''b'')','visible','on'); - set(handles.brline,'ydata',[SET(NO).LevelSet.View.RSlice SET(NO).LevelSet.View.RSlice],... - 'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''b'')','visible','on'); +if isequal(SET(NO).Modality,'CT') %&& ~isempty(regexpi(class(SET(NO).IM),'int')) + mintext = sprintf('%d HU',round(windowmin)); + maxtext = sprintf('%d HU',round(windowmax)); +else + mintext = sprintf('%d',windowmin); + maxtext = sprintf('%d',windowmax); end -%------------------------------------ -function updatemodeldisplay(no,panel) -%------------------------------------ -%Update data used to correctly display segmentation in montage view. This -%fcn needs to be called when the segmentation has changed. -global DATA SET NO +set(DATA.Handles.mappingaxes,'xtick',[windowmin windowmax],... + 'xticklabel',{mintext maxtext}); -if DATA.Run - %No need to update if movie is playing - return -end +%Plot center line +extra = (windowmax-windowmin)*0.1; +hold(DATA.Handles.mappingaxes,'on'); +plot(DATA.Handles.mappingaxes,[windowmin-extra windowmax+extra],[0 0],'k:'); -if nargin < 2 - panel = DATA.CurrentPanel; -end -if nargin==0 - no = NO; -end; - -%--- Check for size of structures -%EndoX -if ~isempty(SET(no).EndoX) - SET(no).EndoXView = nan((length(SET(no).EndoX)+1)*SET(no).ZSize,SET(no).TSize); - SET(no).EndoYView = SET(no).EndoXView; -else - SET(no).EndoXView = NaN; - SET(no).EndoYView = NaN; -end; -%RVEndo -if ~isempty(SET(no).RVEndoX) - SET(no).RVEndoXView = nan((length(SET(no).RVEndoX)+1)*SET(no).ZSize,SET(no).TSize); - SET(no).RVEndoYView = SET(no).RVEndoXView; -else - SET(no).RVEndoXView = NaN; - SET(no).RVEndoYView = NaN; -end; -%RVEpi -if ~isempty(SET(no).RVEpiX) - SET(no).RVEpiXView = nan((length(SET(no).RVEpiX)+1)*SET(no).ZSize,SET(no).TSize); - SET(no).RVEpiYView = SET(no).RVEpiXView; -else - SET(no).RVEpiXView = NaN; - SET(no).RVEpiYView = NaN; -end; -%Epi -if ~isempty(SET(no).EpiX) - SET(no).EpiXView = nan((length(SET(no).EpiX)+1)*SET(no).ZSize,SET(no).TSize); - SET(no).EpiYView = SET(no).EpiXView; -else - SET(no).EpiXView = NaN; - SET(no).EpiYView = NaN; -end; +%Get coordinates of the points +[x1,y1,x2,y2,x3,y3] = getpointcoordinates(NO,x,y); -temp = cell(SET(no).TSize,1); +%Add markers to move the lines +DATA.Handles.speedpoint1 = plot(DATA.Handles.mappingaxes,x1,y1,'bo'); +DATA.Handles.speedpoint2 = plot(DATA.Handles.mappingaxes,x2,y2,'bo'); +DATA.Handles.speedpoint3 = plot(DATA.Handles.mappingaxes,x3,y3,'bo'); +set(DATA.Handles.speedpoint1,'markersize',8,'buttondownfcn','segment3dp.tools(''speedpoint1buttondown'')'); +set(DATA.Handles.speedpoint2,'markersize',8,'buttondownfcn','segment3dp.tools(''speedpoint2buttondown'')'); +set(DATA.Handles.speedpoint3,'markersize',8,'buttondownfcn','segment3dp.tools(''speedpoint3buttondown'')'); -if isempty(SET(no).EndoPinX) - SET(no).EndoPinXView = []; - SET(no).EndoPinYView = []; -else - SET(no).EndoPinXView = temp; - SET(no).EndoPinYView = temp; -end; -if isempty(SET(no).EpiPinX) - SET(no).EpiPinXView = []; - SET(no).EpiPinYView = []; -else - SET(no).EpiPinXView = temp; - SET(no).EpiPinYView = temp; -end; -if isempty(SET(no).RVEndoPinX) - SET(no).RVEndoPinXView = []; - SET(no).RVEndoPinYView = []; -else - SET(no).RVEndoPinXView = temp; - SET(no).RVEndoPinYView = temp; -end; -if isempty(SET(no).RVEpiPinX) - SET(no).RVEpiPinXView = []; - SET(no).RVEpiPinYView = []; -else - SET(no).RVEpiPinXView = temp; - SET(no).RVEpiPinYView = temp; -end; +hold(DATA.Handles.mappingaxes,'off'); -if isempty(SET(no).EndoInterpX) - SET(no).EndoInterpXView = []; - SET(no).EndoInterpYView = []; -else - SET(no).EndoInterpXView = temp; - SET(no).EndoInterpYView = temp; -end; -if isempty(SET(no).EpiInterpX) - SET(no).EpiInterpXView = []; - SET(no).EpiInterpYView = []; -else - SET(no).EpiInterpXView = temp; - SET(no).EpiInterpYView = temp; -end; -if isempty(SET(no).RVEndoInterpX) - SET(no).RVEndoInterpXView = []; - SET(no).RVEndoInterpYView = []; -else - SET(no).RVEndoInterpXView = temp; - SET(no).RVEndoInterpYView = temp; -end; -if isempty(SET(no).RVEpiInterpX) - SET(no).RVEpiInterpXView = []; - SET(no).RVEpiInterpYView = []; -else - SET(no).RVEpiInterpXView = temp; - SET(no).RVEpiInterpYView = temp; -end; - -%TODO: Semi-vectorize the contours so they can fit into the optimized -% single-loop below this double-loop. /JU - -for zloop=1:SET(no).ZSize - [xofsall,yofsall] = calcfunctions('calcoffset',zloop,[],no,panel); %[] was 'montage' - xofs = xofsall; - yofs = yofsall; - for tloop=1:SET(no).TSize - if numel(xofsall) > 1 - xofs = xofsall(tloop); - yofs = yofsall(tloop); - end - %zloop = SET(no).SAX3.slices{loop,tloop}; - - %Endocontour - if ~isempty(SET(no).EndoX) - SET(no).EndoXView((1+(zloop-1)*(size(SET(no).EndoX,1)+1)):(zloop*(size(SET(no).EndoX,1)+1)-1),tloop) = ... - SET(no).EndoX(:,tloop,zloop)+xofs; - SET(no).EndoYView((1+(zloop-1)*(size(SET(no).EndoX,1)+1)):(zloop*(size(SET(no).EndoX,1)+1)-1),tloop) = ... - SET(no).EndoY(:,tloop,zloop)+yofs; - end; - %Epicontour - if ~isempty(SET(no).EpiX) - SET(no).EpiXView((1+(zloop-1)*(size(SET(no).EpiX,1)+1)):(zloop*(size(SET(no).EpiX,1)+1)-1),tloop) = ... - SET(no).EpiX(:,tloop,zloop)+xofs; - SET(no).EpiYView((1+(zloop-1)*(size(SET(no).EpiX,1)+1)):(zloop*(size(SET(no).EpiX,1)+1)-1),tloop) = ... - SET(no).EpiY(:,tloop,zloop)+yofs; - end; - %RV Endocontour - if ~isempty(SET(no).RVEndoX) - SET(no).RVEndoXView((1+(zloop-1)*(size(SET(no).RVEndoX,1)+1)):(zloop*(size(SET(no).RVEndoX,1)+1)-1),tloop) = ... - SET(no).RVEndoX(:,tloop,zloop)+xofs; - SET(no).RVEndoYView((1+(zloop-1)*(size(SET(no).RVEndoX,1)+1)):(zloop*(size(SET(no).RVEndoX,1)+1)-1),tloop) = ... - SET(no).RVEndoY(:,tloop,zloop)+yofs; - end; - %RV Epicontour - if ~isempty(SET(no).RVEpiX) - SET(no).RVEpiXView((1+(zloop-1)*(size(SET(no).RVEpiX,1)+1)):(zloop*(size(SET(no).RVEpiX,1)+1)-1),tloop) = ... - SET(no).RVEpiX(:,tloop,zloop)+xofs; - SET(no).RVEpiYView((1+(zloop-1)*(size(SET(no).RVEpiX,1)+1)):(zloop*(size(SET(no).RVEpiX,1)+1)-1),tloop) = ... - SET(no).RVEpiY(:,tloop,zloop)+yofs; - end; - - % %Endopin - % if ~isempty(SET(no).EndoPinX) - % SET(no).EndoPinXView{tloop} = [... - % SET(no).EndoPinXView{tloop};... - % SET(no).EndoPinX{tloop,zloop}+xofs]; - % SET(no).EndoPinYView{tloop} = [... - % SET(no).EndoPinYView{tloop};... - % SET(no).EndoPinY{tloop,zloop}+yofs]; - % end; - % %Epipin - % if ~isempty(SET(no).EpiPinX) - % SET(no).EpiPinXView{tloop} = [... - % SET(no).EpiPinXView{tloop};... - % SET(no).EpiPinX{tloop,zloop}+xofs]; - % SET(no).EpiPinYView{tloop} = [... - % SET(no).EpiPinYView{tloop};... - % SET(no).EpiPinY{tloop,zloop}+yofs]; - % end; - % %RVEndopin - % if ~isempty(SET(no).RVEndoPinX) - % SET(no).RVEndoPinXView{tloop} = [... - % SET(no).RVEndoPinXView{tloop};... - % SET(no).RVEndoPinX{tloop,zloop}+xofs]; - % SET(no).RVEndoPinYView{tloop} = [... - % SET(no).RVEndoPinYView{tloop};... - % SET(no).RVEndoPinY{tloop,zloop}+yofs]; - % end; - % %RVEpipin - % if ~isempty(SET(no).RVEpiPinX) - % SET(no).RVEpiPinXView{tloop} = [... - % SET(no).RVEpiPinXView{tloop};... - % SET(no).RVEpiPinX{tloop,zloop}+xofs]; - % SET(no).RVEpiPinYView{tloop} = [... - % SET(no).RVEpiPinYView{tloop};... - % SET(no).RVEpiPinY{tloop,zloop}+yofs]; - % end; - % - % %Endo Interp Pts - % if ~isempty(SET(no).EndoInterpX) - % SET(no).EndoInterpXView{tloop} = [... - % SET(no).EndoInterpXView{tloop};... - % SET(no).EndoInterpX{tloop,zloop}+xofs]; - % SET(no).EndoInterpYView{tloop} = [... - % SET(no).EndoInterpYView{tloop};... - % SET(no).EndoInterpY{tloop,zloop}+yofs]; - % end; - % %Epi Interp Pts - % if ~isempty(SET(no).EpiInterpX) - % SET(no).EpiInterpXView{tloop} = [... - % SET(no).EpiInterpXView{tloop};... - % SET(no).EpiInterpX{tloop,zloop}+xofs]; - % SET(no).EpiInterpYView{tloop} = [... - % SET(no).EpiInterpYView{tloop};... - % SET(no).EpiInterpY{tloop,zloop}+yofs]; - % end; - % %RVEndo Interp Pts - % if ~isempty(SET(no).RVEndoInterpX) - % SET(no).RVEndoInterpXView{tloop} = [... - % SET(no).RVEndoInterpXView{tloop};... - % SET(no).RVEndoInterpX{tloop,zloop}+xofs]; - % SET(no).RVEndoInterpYView{tloop} = [... - % SET(no).RVEndoInterpYView{tloop};... - % SET(no).RVEndoInterpY{tloop,zloop}+yofs]; - % end; - % %RVEpi Interp Pts - % if ~isempty(SET(no).RVEpiInterpX) - % SET(no).RVEpiInterpXView{tloop} = [... - % SET(no).RVEpiInterpXView{tloop};... - % SET(no).RVEpiInterpX{tloop,zloop}+xofs]; - % SET(no).RVEpiInterpYView{tloop} = [... - % SET(no).RVEpiInterpYView{tloop};... - % SET(no).RVEpiInterpY{tloop,zloop}+yofs]; - % end; - - end; %tloop -end; %zloop +%Adjust color and limits +set(DATA.Handles.mappingaxes,'xlim',[windowmin-extra windowmax+extra],'ylim',[-1.05 1.05],... + 'xcolor',fgc,... + 'ycolor',fgc,... + 'zcolor',fgc); + +hv = [... + DATA.Handles.decreaseintensitypushbutton ... + DATA.Handles.increaseintensitypushbutton ... + DATA.Handles.decreaseoffsetpushbutton ... + DATA.Handles.centeredit ... + DATA.Handles.increaseoffsetpushbutton ... + DATA.Handles.slopetext ... + DATA.Handles.widthedit ... + DATA.Handles.positivesloperadiobutton ... + DATA.Handles.negativesloperadiobutton ... + DATA.Handles.gaussianradiobutton ... + DATA.Handles.pickpushbutton ... + DATA.Handles.predefinedlistbox ... + DATA.Handles.windowtext ... + DATA.Handles.centertext ... + ]; +set(hv,'Backgroundcolor',bgc,'Foregroundcolor',fgc); -%check to eliminate 1*0 matrix in Interpcells -if ~isempty(SET(no).EndoInterpX) - [SET(no).EndoInterpX{cellfun('isempty',SET(no).EndoInterpX)}]=deal([]); - [SET(no).EndoInterpY{cellfun('isempty',SET(no).EndoInterpY)}]=deal([]); -end -if ~isempty(SET(no).EpiInterpX) - [SET(no).EpiInterpX{cellfun('isempty',SET(no).EpiInterpX)}]=deal([]); - [SET(no).EpiInterpY{cellfun('isempty',SET(no).EpiInterpY)}]=deal([]); -end -if ~isempty(SET(no).RVEndoInterpX) - [SET(no).RVEndoInterpX{cellfun('isempty',SET(no).RVEndoInterpX)}]=deal([]); - [SET(no).RVEndoInterpY{cellfun('isempty',SET(no).RVEndoInterpY)}]=deal([]); -end -if ~isempty(SET(no).RVEpiInterpX) - [SET(no).RVEpiInterpX{cellfun('isempty',SET(no).RVEpiInterpX)}]=deal([]); - [SET(no).RVEpiInterpY{cellfun('isempty',SET(no).RVEpiInterpY)}]=deal([]); -end +%---------------------------------------- +function drawintersectionpoints(no,panel) +%---------------------------------------- +%Initiate handles and draw intersections with other contours +global DATA -[cellx,celly]=calcfunctions('calcoffsetcells',no,panel); -for tloop=1:SET(no).TSize - %Interp Pts - if ~isempty(SET(no).EndoInterpX) && tloop<=size(SET(no).EndoInterpX,1)%&&~isempty(cell2mat(SET(no).EndoInterpX(tloop,:))) - SET(no).EndoInterpXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EndoInterpX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).EndoInterpYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EndoInterpY(tloop,:)',celly,'UniformOutput',0)); - end - if ~isempty(SET(no).EpiInterpX) && tloop<=size(SET(no).EpiInterpX,1) - SET(no).EpiInterpXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EpiInterpX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).EpiInterpYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EpiInterpY(tloop,:)',celly,'UniformOutput',0)); - end - if ~isempty(SET(no).RVEndoInterpX)&& tloop<=size(SET(no).RVEndoInterpX,1) - SET(no).RVEndoInterpXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEndoInterpX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).RVEndoInterpYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEndoInterpY(tloop,:)',celly,'UniformOutput',0)); - end - if ~isempty(SET(no).RVEpiInterpX) && tloop<=size(SET(no).RVEpiInterpX,1) - SET(no).RVEpiInterpXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEpiInterpX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).RVEpiInterpYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEpiInterpY(tloop,:)',celly,'UniformOutput',0)); - end - - %Pins - if ~isempty(SET(no).EndoPinX) - SET(no).EndoPinXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EndoPinX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).EndoPinYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EndoPinY(tloop,:)',celly,'UniformOutput',0)); - end - if ~isempty(SET(no).EpiPinX) - SET(no).EpiPinXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EpiPinX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).EpiPinYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).EpiPinY(tloop,:)',celly,'UniformOutput',0)); - end - if ~isempty(SET(no).RVEndoPinX) - SET(no).RVEndoPinXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEndoPinX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).RVEndoPinYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEndoPinY(tloop,:)',celly,'UniformOutput',0)); - end - if ~isempty(SET(no).RVEpiPinX) - SET(no).RVEpiPinXView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEpiPinX(tloop,:)',cellx,'UniformOutput',0)); - SET(no).RVEpiPinYView{tloop}=cell2mat(cellfun(@plus,... - SET(no).RVEpiPinY(tloop,:)',celly,'UniformOutput',0)); +if isempty(DATA.Handles.hideothercontouricon) || isequal(get(DATA.Handles.hideothercontouricon,'state'),'off') + [endointersectline,maxintersect] = segment('getendointersection',no); + viewtype = DATA.ViewPanelsType{panel}; + [endox,endoy] = calcfunctions('calcsegmentationintersections',no,'endo',viewtype); + [epix,epiy] = calcfunctions('calcsegmentationintersections',no,'epi',viewtype); + [rvendox,rvendoy] = calcfunctions('calcsegmentationintersections',no,'rvendo',viewtype); + [rvepix,rvepiy] = calcfunctions('calcsegmentationintersections',no,'rvepi',viewtype); + + DATA.Handles.endointersectionline{panel} = zeros(1,maxintersect); + for i=1:maxintersect + if(i<=length(endointersectline)) + n = endointersectline(i).NPoints; + DATA.Handles.endointersectionline{panel}(i) = plot(DATA.Handles.imageaxes(panel),... + endointersectline(i).Y(1:n),endointersectline(i).X(1:n),'r'); + else + % create empty handle for intersections in other time frames + DATA.Handles.endointersectionline{panel}(i) = plot(DATA.Handles.imageaxes(panel),... + [0 1],[0 1],'r'); + set(DATA.Handles.endointersectionline{panel}(i),'visible','off'); end + end + DATA.Handles.endointersectionpoints{panel} = plot(DATA.Handles.imageaxes(panel),... + endoy,endox,'r.'); + DATA.Handles.epiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... + epiy,epix,'g.'); + DATA.Handles.rvendointersection{panel} = plot(DATA.Handles.imageaxes(panel),... + rvendoy,rvendox,'m.'); + DATA.Handles.rvepiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... + rvepiy,rvepix,'c.'); +else + for i = 1:length(DATA.Handles.endointersectionline{panel}) + DATA.Handles.endointersectionline{panel}(i) = plot(DATA.Handles.imageaxes(panel),... + NaN,NaN,'r'); + end + DATA.Handles.endointersectionpoints{panel} = plot(DATA.Handles.imageaxes(panel),... + NaN,NaN,'r.'); + DATA.Handles.epiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... + NaN,NaN,'g.'); + DATA.Handles.rvendointersection{panel} = plot(DATA.Handles.imageaxes(panel),... + NaN,NaN,'m.'); + DATA.Handles.rvepiintersection{panel} = plot(DATA.Handles.imageaxes(panel),... + NaN,NaN,'c.'); end -%------------------------------- -function s = cellref(a,varargin) -%------------------------------- -%Returns vector of content of e(varargin), for all elements e of cell a -if ~iscell(a{1}) - s = nan(1,numel(a)*sum(varargin{1}~=0)); +if ~DATA.Pref.BlackWhite + set(DATA.Handles.endointersectionpoints{panel},'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.epiintersection{panel},'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.rvendointersection{panel},'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.rvepiintersection{panel},'markersize',DATA.Pref.MarkerSize); else - s = cell(1,numel(a)*sum(varargin{1}~=0)); -end -n = numel(s)/numel(a); -for i = 1:numel(a) - s((i-1)*n+(1:n)) = a{i}(varargin{:}); + set(DATA.Handles.endointersectionline{panel},'color',[1 1 1]); + set(DATA.Handles.endointersectionpoints{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); + set(DATA.Handles.epiintersection{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); + set(DATA.Handles.rvendointersection{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); + set(DATA.Handles.rvepiintersection{panel},'markersize',DATA.Pref.MarkerSize,'color',[1 1 1]); end -%---------------------------------- -function updateglazoomstate(no,ysz) -%---------------------------------- -%This function helps with updating the zoom for the gla view when in -%orthoview mode. -global SET -xzoomsz = max(SET(no).XSize,SET(no).YSize); -repos = (ysz-xzoomsz)/2; -SET(no).GLA.ZoomState = 0.5+[repos+[0;xzoomsz];0;SET(no).ZSize]; - - - -function drawimagetypetext3dp(no,panel) %--------------------------------------- -%Writes text describing image type in imagepanel +function updateintersectionpoints(panel) +%--------------------------------------- +%Draw intersection with segmentation in other image stacks -global DATA SET -x = SET(no).YSize*0.9; -y = SET(no).XSize*0.9; - -if (strcmp(DATA.CurrentTheme,'3dp')) - if (strcmp(DATA.ViewPanelsType{panel},'sag3DP')); - stri=dprintf('Slice:%02d',SET(no).LevelSet.View.GSlice); - DATA.Handles.slicetimetext3dp(panel) = text(... - x,... - y,... - stri,'interpreter','none'); - extent = get(DATA.Handles.slicetimetext3dp(panel),'extent'); - set(DATA.Handles.slicetimetext3dp(panel),... - 'interpreter','none',... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-extent(4) 0]); - - striZ = dprintf('Y:%.3f',SET(no).LevelSet.View.GSlice*SET(no).ResolutionY); - DATA.Handles.slicecoordtext3dp(panel) = text(... - x,... - size(DATA.ViewIM{panel},1)-2*extent(4),... - striZ,'interpreter','none','color','white'); - - elseif (strcmp(DATA.ViewPanelsType{panel},'trans3DP')); - - stri=dprintf('Slice:%02d',SET(no).LevelSet.View.RSlice); - DATA.Handles.slicetimetext3dp(panel) = text(... - x,... - y,... - stri,'interpreter','none'); - extent = get(DATA.Handles.slicetimetext3dp(panel),'extent'); - set(DATA.Handles.slicetimetext3dp(panel),... - 'interpreter','none',... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-extent(4) 0]); - - - striZ = dprintf('Z:%.3f',SET(no).LevelSet.View.RSlice*((SET(no).SliceThickness+SET(no).SliceGap))); - DATA.Handles.slicecoordtext3dp(panel) = text(... - x,... - size(DATA.ViewIM{panel},1)-2*extent(4),... - striZ,'interpreter','none','color','white'); - - elseif (strcmp(DATA.ViewPanelsType{panel},'cor3DP')); - stri=dprintf('Slice:%02d',SET(no).LevelSet.View.BSlice); - DATA.Handles.slicetimetext3dp(panel) = text(... - x,... - y,... - stri,'interpreter','none'); - extent = get(DATA.Handles.slicetimetext3dp(panel),'extent'); - set(DATA.Handles.slicetimetext3dp(panel),... - 'interpreter','none',... - 'color','white','position',... - [size(DATA.ViewIM{panel},2)-extent(3) ... - size(DATA.ViewIM{panel},1)-extent(4) 0]); - - striZ = dprintf('X:%.3f',SET(no).LevelSet.View.BSlice*(SET(no).ResolutionX)); - DATA.Handles.slicecoordtext3dp(panel) = text(... - x,... - size(DATA.ViewIM{panel},1)-2*extent(4),... - striZ,'interpreter','none','color','white'); - -% elseif (strcmp(DATA.ViewPanelsType{panel},'speedim')); %to reject -% stri=dprintf('X:%02d',SET(no).LevelSet.View.BSlice); -% DATA.Handles.slicetimetext3dp(panel) = text(... -% x,... -% y,... -% stri,'interpreter','none'); -% extent = get(DATA.Handles.slicetimetext3dp(panel),'extent'); -% set(DATA.Handles.slicetimetext3dp(panel),... -% 'interpreter','none',... -% 'color','white','position',... -% [size(DATA.ViewIM{panel},2)-extent(3) ... -% size(DATA.ViewIM{panel},1)-extent(4) 0]); -% -% striZ = dprintf('X:%.3f',SET(no).LevelSet.View.BSlice*(SET(no).ResolutionX)); -% DATA.Handles.slicecoordtext3dp(panel) = text(... -% x,... -% size(DATA.ViewIM{panel},1)-2*extent(4),... -% striZ,'interpreter','none','color','white'); - end +global DATA +no = DATA.ViewPanels(panel(1)); +viewtype = DATA.ViewPanelsType{panel}; +if ~isequal(get(DATA.Handles.hideothercontouricon,'state'),'on') + endointersect = segment('getendointersection',no); + [endox,endoy] = calcfunctions('calcsegmentationintersections',no,'endo',viewtype); + [epix,epiy] = calcfunctions('calcsegmentationintersections',no,'epi',viewtype); + [rvendox,rvendoy] = calcfunctions('calcsegmentationintersections',no,'rvendo',viewtype); + [rvepix,rvepiy] = calcfunctions('calcsegmentationintersections',no,'rvepi',viewtype); + set(DATA.Handles.endointersectionline{panel},'visible','off'); + for i=1:length(endointersect) + n = endointersect(i).NPoints; + set(cellref(DATA.Handles.endointersectionline(panel),i),'xdata',endointersect(i).Y(1:n),... + 'ydata',endointersect(i).X(1:n),'visible','on'); end + if ~isempty([endox epix rvendox rvepix]) + set([DATA.Handles.endointersectionpoints{panel}], ... + 'XData',endoy,'YData',endox); + set([DATA.Handles.epiintersection{panel}], ... + 'XData',epiy,'YData',epix); + set([DATA.Handles.rvendointersection{panel}], ... + 'XData',rvendoy,'YData',rvendox); + set([DATA.Handles.rvepiintersection{panel}], ... + 'XData',rvepiy,'YData',rvepix); + end +end +%--------------------------------------- +function updateinterpolationsettings(panel,type) +%--------------------------------------- +global DATA +DATA.Handles.([lower(type),'contour'])(panel).LineStyle = 'none'; +DATA.Handles.([lower(type),'contour'])(panel).Marker = '.'; +DATA.Handles.([lower(type),'contour'])(panel).MarkerSize = 4; -viewupdatetextposition3dp(panel); - -%------------------------------------- -function viewupdatetextposition3dp(panel) -%------------------------------------- -% Updates the location of the corner text, to always stay still. -% From drawx(), it is called panelwise, since the linked panels aren't -% ready when the first panel is drawn. From other situations, it is called -% without arguements, and handles the linkage by itself. /JU - -global DATA SET NO - -%Input to force black background around corner text to improve visibility -if DATA.Pref.BackgroundColor - bgcolor = 'blue'; -else - bgcolor = 'none'; +%--------------------------------------- +function updatexydata(handlename,panel,szim) +%--------------------------------------- +% this function updates XData and YData depending on the scale and image +% size +global DATA -myset(DATA.Handles.slicetimetext3dp,'BackgroundColor',bgcolor) -myset(DATA.Handles.slicecoordtext3dp,'BackgroundColor',bgcolor) -end -if nargin==1 - ind = panel; +if DATA.Pref.ViewInterpolated && strcmp(DATA.ViewPanelsType{panel},'one') + %Assume scale = 2 + DATA.Handles.(handlename)(panel).XData = 1.5:1:szim(2)+0.5; %XData is corner coordinates for image + DATA.Handles.(handlename)(panel).YData = 1.5:1:szim(1)+0.5; else - no = NO; - nos=SET(no).Linked; - ind = []; - for loop=1:length(nos) - ind = [ind find(DATA.ViewPanels==nos(loop))]; %#ok - end; - ind = unique(ind); %remove duplicates. - ind = ind(~strcmp(DATA.ViewPanelsType(ind),'mmodetemporal')); + DATA.Handles.(handlename)(panel).XData = 1:1:szim(2); %XData is corner coordinates for image + DATA.Handles.(handlename)(panel).YData = 1:1:szim(1); end - -%if ~any(strcmp(DATA.ProgramName,{'Segment 3DPrint'})) - for panel=ind - xlim=get(DATA.Handles.imageaxes(panel),'xlim'); - ylim=get(DATA.Handles.imageaxes(panel),'ylim'); - - - extent = get(DATA.Handles.slicetimetext3dp(panel),'extent'); - set(DATA.Handles.slicetimetext3dp(panel),'color','white','position',... - [xlim(2)-extent(3) ... - ylim(2)-extent(4) 0]); - - extent = get(DATA.Handles.slicecoordtext3dp(panel),'extent'); - set(DATA.Handles.slicecoordtext3dp(panel),'color','white','position',... - [xlim(2)-extent(3) ... - ylim(2)-2*extent(4) 0]); - end diff --git a/source/ebbwlabel.mexw32 b/source/ebbwlabel.mexw32 deleted file mode 100644 index f7c67cc..0000000 Binary files a/source/ebbwlabel.mexw32 and /dev/null differ diff --git a/source/echoscu.exe b/source/echoscu.exe index 6ffb7b5..7e43253 100644 Binary files a/source/echoscu.exe and b/source/echoscu.exe differ diff --git a/source/econv3.mexw32 b/source/econv3.mexw32 deleted file mode 100644 index 1094eff..0000000 Binary files a/source/econv3.mexw32 and /dev/null differ diff --git a/source/ecv.m b/source/ecv.m index f32ab6f..86bc139 100644 --- a/source/ecv.m +++ b/source/ecv.m @@ -81,7 +81,7 @@ multislice = true; if length(preno) > 1 || length(postno) > 1 %if multi-slice data, use only NO if that is applicable - if ismember(NO,[preno postno]); + if ismember(NO,[preno postno]) if ismember(NO,preno) prenonbr = find(ismember(NO,preno)); suggestedpostno = postno(min(prenonbr,length(postno))); @@ -124,8 +124,7 @@ %error checks if isempty(preno) || isempty(postno) - myfailed(['Could not find T1 map pre or T1 map post image stacks with' ... - ' ROI''s labelled ''Blood''.']); + myfailed(['Could not find T1 map pre or T1 map post image stacks with ROI''s labelled ''Blood''.']); return end if length(preno) ~= length(postno) %SET(preno).ZSize ~= SET(postno).ZSize @@ -139,7 +138,7 @@ %ask for the hematocrit value while true - hem = inputdlg('Hematocrit [0 1]','Input value'); + hem = myinputdlg('Hematocrit [0 1]','Input value'); if isempty(hem) return else @@ -185,7 +184,7 @@ end %find time frame while true - premaptftemp = inputdlg(askstri,'Pre T1 map',1,guess); + premaptftemp = myinputdlg(askstri,'Pre T1 map',1,guess); if isempty(premaptftemp) return; end @@ -241,7 +240,7 @@ end end while true - postmaptftemp = inputdlg(askstri,'Post T1 maps',1,guess); + postmaptftemp = myinputdlg(askstri,'Post T1 maps',1,guess); if isempty(postmaptftemp) return; end @@ -277,7 +276,7 @@ end end while true - coupledpostnotemp = inputdlg(askstri,'Pre T1 maps',1,guess); + coupledpostnotemp = myinputdlg(askstri,'Pre T1 maps',1,guess); if isempty(coupledpostnotemp) return; end @@ -398,7 +397,7 @@ end while true - hem = inputdlg('Hematocrit','Input value'); + hem = myinputdlg('Hematocrit','Input value'); if isempty(hem) return else @@ -514,7 +513,8 @@ function opengui(preno,postno,hem,premaptf,postmaptf,multislice,lvsegslicepre,lv [SET(postno(k)).XSize SET(postno(k)).YSize],... postroi.Y(:,postmaptf(k)),postroi.X(:,postmaptf(k))); postim = calcfunctions('calctruedata',postT1maptemp(:,:,1,postroi.Z),postno(k)); - postblood = repmat(mean(postim(postmask)),[1 length(lvsegslicepre)]); + postbloodtemp = repmat(mean(postim(postmask)),[1 length(lvsegslicepre)]); + postblood(lvsegslicepre) = postbloodtemp; else myfailed('No ROI labeled ''Blood'' found in post T1 map'); return; @@ -557,7 +557,8 @@ function opengui(preno,postno,hem,premaptf,postmaptf,multislice,lvsegslicepre,lv [SET(preno(k)).XSize SET(preno(k)).YSize],... preroi.Y(:,premaptf(k)),preroi.X(:,premaptf(k))); preim = calcfunctions('calctruedata',preT1maptemp(:,:,1,preroi.Z),preno(k)); - preblood = repmat(mean(preim(premask)),[1 length(lvsegslicepre)]); + prebloodtemp = repmat(mean(preim(premask)),[1 length(lvsegslicepre)]); + preblood(lvsegslicepre) = prebloodtemp; else myfailed('No ROI labeled ''Blood'' found in pre T1 map'); return; @@ -738,7 +739,7 @@ function opengui(preno,postno,hem,premaptf,postmaptf,multislice,lvsegslicepre,lv end %%%%%%%%%%%%%%%% Open GUI %%%%%%%%%%%%%%%%% -if isopengui('ecvregistration.fig'); +if isopengui('ecvregistration.fig') gui = DATA.GUI.ECVRegistration; figure(gui.fig); else @@ -1022,8 +1023,8 @@ function plotimages(multislice,lvsegslicepre,lvsegslicepost) preT1mapimage = preT1mapimage *1/max(preT1mapimage (:)); postT1mapalignedimage = postT1mapalignedimage *1/max(postT1mapalignedimage (:)); %set colormap - viewimpre = spect.spectperfusionsegmentation('remapuint8',preT1mapimage,graymap); - viewimpost = spect.spectperfusionsegmentation('remapuint8',postT1mapalignedimage,graymap); + viewimpre = calcfunctions('remapuint8modified',preT1mapimage,graymap); + viewimpost = calcfunctions('remapuint8modified',postT1mapalignedimage,graymap); %plot images gui.handles.preimage = imagesc(viewimpre,'parent',gui.handles.preaxes); gui.handles.postimage = imagesc(viewimpost,'parent',gui.handles.postaxes); @@ -1060,8 +1061,8 @@ function plotimages(multislice,lvsegslicepre,lvsegslicepost) viewimpost = viewimpost*1/max(viewimpost(:)); %create visulaization images - viewimpremap = spect.spectperfusionsegmentation('remapuint8',viewimpre,graymap); - viewimpostmap = spect.spectperfusionsegmentation('remapuint8',viewimpost,graymap); + viewimpremap = calcfunctions('remapuint8modified',viewimpre,graymap); + viewimpostmap = calcfunctions('remapuint8modified',viewimpost,graymap); %plot images gui.handles.preimage = imagesc(viewimpremap,'parent',gui.handles.preaxes); @@ -1073,13 +1074,13 @@ function plotimages(multislice,lvsegslicepre,lvsegslicepost) %plot colorbars precolorbartemp = linspace(0,1,255); -precolorbar = spect.spectperfusionsegmentation('remapuint8',flipud(precolorbartemp'),graymap); +precolorbar = calcfunctions('remapuint8modified',flipud(precolorbartemp'),graymap); gui.handles.precolorbarimage = imagesc(precolorbar,'parent',gui.handles.precolorbaraxes); -set(gui.handles.precolorbaraxes,'ytick',linspace(1,255,11),'YTickLabel',linspace(gui.viewmaxpre,0,11),'YAxisLocation','right','xtick',[]); +set(gui.handles.precolorbaraxes,'ytick',linspace(1,255,11),'YTickLabel',linspace(gui.viewmaxpre,0,11),'YAxisLocation','right','xtick',[],'YColor',DATA.GUISettings.ForegroundColor); postcolorbartemp = linspace(0,1,255); -postcolorbar = spect.spectperfusionsegmentation('remapuint8',flipud(postcolorbartemp'),graymap); +postcolorbar = calcfunctions('remapuint8modified',flipud(postcolorbartemp'),graymap); gui.handles.postcolorbarimage = imagesc(postcolorbar,'parent',gui.handles.postcolorbaraxes); -set(gui.handles.postcolorbaraxes,'ytick',linspace(1,255,11),'YTickLabel',linspace(gui.viewmaxpost,0,11),'YAxisLocation','right','xtick',[]); +set(gui.handles.postcolorbaraxes,'ytick',linspace(1,255,11),'YTickLabel',linspace(gui.viewmaxpost,0,11),'YAxisLocation','right','xtick',[],'YColor',DATA.GUISettings.ForegroundColor); %--------------- @@ -1100,7 +1101,7 @@ function plotecv(multislice,lvsegslicepre) if length(gui.preno) == 1 && not(multislice) nbrrows = 1; - viewimecv = spect.spectperfusionsegmentation('remapuint8',gui.ecvmapplot{1},hotmap); + viewimecv = calcfunctions('remapuint8modified',gui.ecvmapplot{1},hotmap); gui.handles.ecvimage = imagesc(viewimecv,'parent',gui.handles.ecvaxes); axis(gui.handles.ecvaxes,'off','image'); set(gui.handles.ecvaxes,'clim',[0 1]); @@ -1122,7 +1123,7 @@ function plotecv(multislice,lvsegslicepre) nbrcols = 1; szpre = size(ecvmapimage); gui.viewimecv = reshape2layout(ecvmapimage,nbrrows,nbrcols,[szpre(1) szpre(2) nbrrows]); - viewimecvmap = spect.spectperfusionsegmentation('remapuint8',gui.viewimecv,hotmap); + viewimecvmap = calcfunctions('remapuint8modified',gui.viewimecv,hotmap); gui.handles.ecvimage = imagesc(viewimecvmap,'parent',gui.handles.ecvaxes); axis(gui.handles.ecvaxes,'off','image') set(gui.handles.ecvaxes,'clim',[0 1]); @@ -1130,9 +1131,9 @@ function plotecv(multislice,lvsegslicepre) %plot ecv colorbar ecvcolorbartemp = linspace(0,1,255); -ecvcolorbar = spect.spectperfusionsegmentation('remapuint8',flipud(ecvcolorbartemp'),hotmap); +ecvcolorbar = calcfunctions('remapuint8modified',flipud(ecvcolorbartemp'),hotmap); gui.handles.ecvcolorbarimage = imagesc(ecvcolorbar,'parent',gui.handles.ecvcolorbaraxes); -set(gui.handles.ecvcolorbaraxes,'ytick',linspace(1,255,11),'YTickLabel',linspace(100,0,11),'YAxisLocation','right','xtick',[]); +set(gui.handles.ecvcolorbaraxes,'ytick',linspace(1,255,11),'YTickLabel',linspace(100,0,11),'YAxisLocation','right','xtick',[],'YColor',DATA.GUISettings.ForegroundColor); %print stack/slice numbers in the lower left corner of the ecv image if nbrrows > 1 @@ -1173,7 +1174,7 @@ function plotLVsegmentation(multislice,lvsegslicepre) nbrrows = length(lvsegslicepre); for zloop = 1:nbrrows zvisualization = zvisualization+1; %zloop-paneldivision(panelloop)+1; - [xofs,yofs] = spect.spectperfusionsegmentation('calcoffset',zvisualization,nbrcols,sz); + [xofs,yofs] = calcfunctions('calcoffsetmodified',zvisualization,nbrcols,sz); %Endocontour gui.handles.endoxView((1+(zvisualization-1)*(DATA.NumPoints+1)):(zvisualization*(DATA.NumPoints+1)-1)) = ... endox(:,1,lvsegslicepre(zloop))+xofs; @@ -1189,7 +1190,7 @@ function plotLVsegmentation(multislice,lvsegslicepre) nbrrows = length(gui.preno); for zloop = 1:nbrrows zvisualization = zvisualization+1; %zloop-paneldivision(panelloop)+1; - [xofs,yofs] = spect.spectperfusionsegmentation('calcoffset',zvisualization,nbrcols,sz); + [xofs,yofs] = calcfunctions('calcoffsetmodified',zvisualization,nbrcols,sz); %Endocontour gui.handles.endoxView((1+(zvisualization-1)*(DATA.NumPoints+1)):(zvisualization*(DATA.NumPoints+1)-1)) = ... gui.endox{zloop}+xofs; @@ -1235,12 +1236,12 @@ function plotROI(multislice,lvsegslicepre) %present ECV result AxesTables = []; AxesTables.result = axestable(gui.handles.reportaxes); -AxesTables.result.backgroundcolor = [0.94 0.94 0.94]; %[0 0 0];% -AxesTables.result.fontcolor = [0 0 0]; % [1 1 1];% +AxesTables.result.backgroundcolor = DATA.GUISettings.BackgroundColor; +AxesTables.result.fontcolor = DATA.GUISettings.ForegroundColor; AxesTables.result.fontsize = 10; AxesTables.result.ystep = 22; -AxesTables.result.addTable(sprintf('ECV Result. Hematocrit: %0.2f',gui.hem),5,4,[0.18 0.25 0.19 0.19 0.19]); -AxesTables.result.addKey('title','Label',[],{'Area[mm2]','Mean','Min','Max'}); +AxesTables.result.addTable(dprintf('ECV Result. Hematocrit: %0.2f',gui.hem),5,4,[0.18 0.25 0.19 0.19 0.19]); +AxesTables.result.addKey('title',dprintf('Label'),[],{dprintf('Area[mm2]'),dprintf('Mean'),dprintf('Min'),dprintf('Max')}); zvisualization = 1; sz = size(gui.preT1map{1}); @@ -1259,13 +1260,13 @@ function plotROI(multislice,lvsegslicepre) %ecv result string roiloop = 1; if multislice - tabletext = sprintf('Slice %0.0f\n',lvsegslicepre(zloop)); + tabletext = dprintf('Slice %0.0f\n',lvsegslicepre(zloop)); roiarea = roiareatemp{zloop}; roiecv = roiecvalignedtemp{zloop}; prerois = allroistemp{zloop}; tfindex = 1; else - tabletext = sprintf('Image stack %0.0f\n',zloop); + tabletext = dprintf('Image stack %0.0f\n',zloop); roiarea = gui.roiarea{zloop}; roiecv = gui.roiecvaligned{zloop}; prerois = gui.rois{zloop}; @@ -1274,7 +1275,7 @@ function plotROI(multislice,lvsegslicepre) AxesTables.result.addTable(tabletext,5,4,[0.2 0.23 0.19 0.19 0.19]); % AxesTables.result.addKey('title2',tabletext,[],{[],[],[],[]}); %ROI contour - [xofs,yofs] = spect.spectperfusionsegmentation('calcoffset',zvisualization,nbrcols,sz); + [xofs,yofs] = calcfunctions('calcoffsetmodified',zvisualization,nbrcols,sz); zvisualization = zvisualization+1; roixView = []; roiyView = []; @@ -1287,7 +1288,7 @@ function plotROI(multislice,lvsegslicepre) preroi.Y(:,gui.premaptf(tfindex))+yofs; roilabelX(roiloop) = mynanmean(preroi.X(:,gui.premaptf(tfindex))+xofs); roilabelY(roiloop) = mynanmean(preroi.Y(:,gui.premaptf(tfindex))+yofs); - AxesTables.result.addKey(preroi.Name,preroi.Name,[],{dprintf('%0.2f',roiarea(roiloop)),round(100*mean(roiecv{roiloop})),round(100*min(roiecv{roiloop})),round(100*max(roiecv{roiloop}))}); + AxesTables.result.addKey(preroi.Name,preroi.Name,[],{sprintf('%0.2f',roiarea(roiloop)),round(100*mean(roiecv{roiloop})),round(100*min(roiecv{roiloop})),round(100*max(roiecv{roiloop}))}); roiloop = roiloop+1; end @@ -1339,8 +1340,8 @@ function plotROI(multislice,lvsegslicepre) preT1mapimage = preT1mapimage *1/max(preT1mapimage (:)); postT1mapplotimage = postT1mapplotimage *1/max(postT1mapplotimage (:)); %create visulaization images - viewimpre = spect.spectperfusionsegmentation('remapuint8',preT1mapimage,graymap); - viewimpost = spect.spectperfusionsegmentation('remapuint8',postT1mapplotimage,graymap); + viewimpre = calcfunctions('remapuint8modified',preT1mapimage,graymap); + viewimpost = calcfunctions('remapuint8modified',postT1mapplotimage,graymap); %plot images set(gui.handles.preimage,'cdata',viewimpre); set(gui.handles.postimage,'cdata',viewimpost); @@ -1376,8 +1377,8 @@ function plotROI(multislice,lvsegslicepre) viewimpost = viewimpost*1/max(viewimpost(:)); %create visulaization images - viewimpremap = spect.spectperfusionsegmentation('remapuint8',viewimpre,graymap); - viewimpostmap = spect.spectperfusionsegmentation('remapuint8',viewimpost,graymap); + viewimpremap = calcfunctions('remapuint8modified',viewimpre,graymap); + viewimpostmap = calcfunctions('remapuint8modified',viewimpost,graymap); %plot images set(gui.handles.preimage,'cdata',viewimpremap); @@ -1405,7 +1406,7 @@ function plotROI(multislice,lvsegslicepre) %plot ECV map if length(gui.preno) == 1 && not(gui.multislice) - viewimecvmap = spect.spectperfusionsegmentation('remapuint8',gui.ecvmapplot{1},hotmap); + viewimecvmap = calcfunctions('remapuint8modified',gui.ecvmapplot{1},hotmap); set(gui.handles.ecvimage,'cdata',viewimecvmap); else @@ -1426,7 +1427,7 @@ function plotROI(multislice,lvsegslicepre) nbrcols = 1; szpre = size(ecvmapimage); gui.viewimecv = reshape2layout(ecvmapimage,nbrrows,nbrcols,[szpre(1) szpre(2) nbrrows]); - viewimecvmap = spect.spectperfusionsegmentation('remapuint8',gui.viewimecv,hotmap); + viewimecvmap = calcfunctions('remapuint8modified',gui.viewimecv,hotmap); set(gui.handles.ecvimage,'cdata',viewimecvmap); end @@ -1473,7 +1474,7 @@ function plotROI(multislice,lvsegslicepre) prerois = gui.rois{zloop}; end for preroi = prerois - updatestruct = {dprintf('%0.2f',roiarea(roiloop)),round(100*mean(roiecv{roiloop})),round(100*min(roiecv{roiloop})),round(100*max(roiecv{roiloop}))}; + updatestruct = {sprintf('%0.2f',roiarea(roiloop)),round(100*mean(roiecv{roiloop})),round(100*min(roiecv{roiloop})),round(100*max(roiecv{roiloop}))}; AxesTables.result.updateKey(preroi.Name,updatestruct,true); roiloop = roiloop+1; end @@ -1688,6 +1689,7 @@ function plotROI(multislice,lvsegslicepre) gui = DATA.GUI.ECVRegistration; + %create ECV map image stack for zloop = 1:length(gui.preno) nbr = length(SET)+1; @@ -1716,8 +1718,11 @@ function plotROI(multislice,lvsegslicepre) [SET(no).YSize,SET(no).OrgYSzie] = deal(size(gui.ecvmap{zloop},1)); [SET(no).CenterX,SET(no).Mmode.X] = deal(round(SET(no).XSize/2)); [SET(no).CenterY,SET(no).Mmode.Y] = deal(round(SET(no).YSize/2)); + SET(no).NormalZoomState = []; SET(no).Linked = no; - annotationpoint('pointclearall'); %erase annotation points + SET(no).Parent = []; + SET(no).Children = no; + callbackfunctions('pointclearall_Callback'); %erase annotation points %fix LV segmentation SET(no).EndoX = gui.endox{zloop}; SET(no).EndoY = gui.endoy{zloop}; @@ -1740,6 +1745,11 @@ function plotROI(multislice,lvsegslicepre) SET(no).Roi(rloop).X = SET(no).Roi(rloop).X(:,gui.premaptf); SET(no).Roi(rloop).Y = SET(no).Roi(rloop).Y(:,gui.premaptf); SET(no).Roi(rloop).T = 1; + [~,area]=calcfunctions('calcroiarea',no,rloop); + SET(no).Roi(rloop).Area = area; + [m,sd]=calcfunctions('calcroiintensity',no,rloop); + SET(no).Roi(rloop).Mean = m; + SET(no).Roi(rloop).StD = sd; end tools('setcolormap_Callback','ecv',no); @@ -1748,11 +1758,20 @@ function plotROI(multislice,lvsegslicepre) SET(no).Scar = []; end + +% +SET(no).ECV.reportecvim = frame2im(mygetframe(gui.handles.ecvaxes)); +SET(no).ECV.reportpreim = frame2im(mygetframe(gui.handles.preaxes)); + + segment('updatevolume'); %Included in next callback?? -segment('viewrefreshall_Callback'); -force = true; -segment('switchtoimagestack',no,force); +viewfunctions('setview',1,1,no,{'one'}) +% segment('viewrefreshall_Callback'); +% force = true; +% segment('switchtoimagestack',no,force); tools('setcolormap_Callback','ecv',no); + + % drawfunctions('drawimageno'); % drawfunctions('drawsliceno'); % drawfunctions('drawall',length(DATA.ViewPanels)); diff --git a/source/ecvregistration.fig b/source/ecvregistration.fig index 35a2e13..6360d05 100644 Binary files a/source/ecvregistration.fig and b/source/ecvregistration.fig differ diff --git a/source/einterp2.mexw32 b/source/einterp2.mexw32 deleted file mode 100644 index 2fdffff..0000000 Binary files a/source/einterp2.mexw32 and /dev/null differ diff --git a/source/existfunctions.m b/source/existfunctions.m index 3422231..05c6334 100644 --- a/source/existfunctions.m +++ b/source/existfunctions.m @@ -20,14 +20,14 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EndoX) || all(isnan(SET(no).EndoX(:))) y = false; else %Tested enough, make true y = true; -end; +end %------------------------ function y = existepi(no) @@ -37,14 +37,14 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EpiX) || all(isnan(SET(no).EpiX(:))) y = false; else %Tested enough, make true y = true; -end; +end %-------------------------------------- @@ -56,12 +56,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EndoX) || all(isnan(SET(no).EndoX(:))) y = false; return; -end; +end if nargin == 3 y = not(anyall(isnan(SET(no).EndoX(... @@ -85,7 +85,7 @@ else y = not(anyall(isnan(SET(no).EndoX(... 1,:,SET(no).StartSlice:SET(no).EndSlice)))); -end; +end %------------------------------------ function y = existepiinselected(no,t,s) %#ok @@ -96,12 +96,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EpiX) y = false; return; -end; +end if nargin == 2 y = not(anyall(isnan(SET(no).EpiX(... @@ -125,7 +125,7 @@ else y = not(anyall(isnan(SET(no).EpiX(... 1,:,SET(no).StartSlice:SET(no).EndSlice)))); -end; +end %----------------------------------- function y = existendoinslices(no,t) %#ok @@ -137,12 +137,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EndoX) || all(isnan(SET(no).EndoX(:))) y = false(SET(no).ZSize,1); return; -end; +end if nargin == 2 y = squeeze(~isnan(SET(no).EndoX(1,t,:))); @@ -162,12 +162,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EpiX) || all(isnan(SET(no).EpiX(:))) y = false(SET(no).ZSize,1); return; -end; +end if nargin == 2 y = squeeze(~isnan(SET(no).EpiX(1,t,:))); @@ -185,12 +185,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).RVEndoX) y = false; return; -end; +end % if strcmp(DATA.ProgramName,'Segment CMR') % DATA.ThisFrameOnly = false; @@ -202,7 +202,7 @@ else y = not(anyall(isnan(SET(no).RVEndoX(... 1,:,SET(no).StartSlice:SET(no).EndSlice)))); -end; +end %------------------------------- function y = existendoonlyinedes(no) %#ok @@ -212,7 +212,7 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EndoX) || all(isnan(SET(no).EndoX(:))) y = false; @@ -239,7 +239,7 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EpiX) || all(isnan(SET(no).EpiX(:))) y = false; @@ -266,7 +266,7 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).RVEndoX) || all(isnan(SET(no).RVEndoX(:))) y = false; @@ -293,7 +293,7 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).RVEpiX) || all(isnan(SET(no).RVEpiX(:))) y = false; diff --git a/source/export.m b/source/export.m index f7a544d..cc840e9 100644 --- a/source/export.m +++ b/source/export.m @@ -16,9 +16,8 @@ pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.'); return; -end; +end files2load = dir([pathname filesep '*.mat']); numfiles = length(files2load); @@ -26,7 +25,7 @@ if numfiles==0 myfailed('No files to do area on found.'); return; -end; +end outdata = cell(numfiles+1,120); @@ -68,12 +67,12 @@ if isempty(cineno) [cineno] = findfunctions('findscarshortaxisno'); disp('Could not find short axis cine stack. Taking scar instead.'); - end; + end if isempty(cineno) disp('Could not find either cine or scar stack. Taking first stack.'); cineno = 1; - end; + end NO = cineno; if SET(cineno).EDT==1 && SET(cineno).EST==1 @@ -101,7 +100,7 @@ disp('No endo- or epicardium exist'); temp = []; else - [outdata{loop+2,7} minindex] = min([endostartslice epistartslice]); + [outdata{loop+2,7}, minindex] = min([endostartslice epistartslice]); if minindex == 1 temp = find(~isnan(SET(cineno).EndoX(1,SET(cineno).EDT,:))); else @@ -111,7 +110,7 @@ if ~isempty(temp) outdata{loop+2,8} = temp(end); - end; + end if maxnumslices<=size(L,1) doslicenumheader = 1; @@ -155,10 +154,10 @@ outdata{loop+2,8+100+sloop} = E(sloop,SET(cineno).EST); outdata{loop+2,8+200+sloop} = L(sloop,SET(cineno).EDT); outdata{loop+2,8+300+sloop} = L(sloop,SET(cineno).EST); - end; - end; + end + end h = mywaitbarupdate(h); -end; +end mywaitbarclose(h); tmp={}; @@ -185,7 +184,7 @@ if SET(NO).Rotated myfailed('Rotated image stacks currently not supported for this operation.',DATA.GUI.Segment); return; -end; +end endo = true; epi = true; @@ -194,22 +193,22 @@ if isempty(SET(NO).EndoX) endo = false; -end; +end if isempty(SET(NO).EpiX) epi = false; -end; +end if isempty(SET(NO).RVEndoX) rvendo = false; -end; +end if isempty(SET(NO).RVEpiX) rvepi = false; -end; +end numcontours = endo+epi+rvendo+rvepi; if (SET(NO).TSize>1)&&(SET(NO).Longaxis>1) mywarning('Automated long axis compensation not included in the export.',DATA.GUI.Segment); -end; +end %Reserve memory outdata = cell(SET(NO).ZSize+8,1+SET(NO).TSize*numcontours); @@ -231,17 +230,17 @@ outdata{2,1+tloop} = sprintf('%d',tloop); if endo outdata{3,1+tloop} = SET(NO).LVV(tloop); - end; + end if epi outdata{4,1+tloop} = SET(NO).EPV(tloop); - end; + end if rvendo outdata{5,1+tloop} = SET(NO).RVV(tloop); - end; + end if rvepi outdata{6,1+tloop} = SET(NO).RVEPV(tloop); - end; -end; + end +end %Find number of ROI's temproinames=cell(1,SET(NO).RoiN); @@ -254,29 +253,29 @@ for zloop=1:SET(NO).ZSize outdata{rowoffset+zloop,1} = sprintf('Slice:%d',zloop); -end; +end coloffset = 1; if endo outdata = exportslicehelper(outdata,rowoffset,coloffset,'Endo',... SET(NO).EndoX,SET(NO).EndoY); coloffset = coloffset+SET(NO).TSize; -end; +end if epi outdata = exportslicehelper(outdata,rowoffset,coloffset,'Epi',... SET(NO).EpiX,SET(NO).EpiY); coloffset = coloffset+SET(NO).TSize; -end; +end if rvendo outdata = exportslicehelper(outdata,rowoffset,coloffset,'RVEndo',... SET(NO).RVEndoX,SET(NO).RVEndoY); coloffset = coloffset+SET(NO).TSize; -end; +end if rvepi outdata = exportslicehelper(outdata,rowoffset,coloffset,'RVEpi',... SET(NO).RVEpiX,SET(NO).RVEpiY); coloffset = coloffset+SET(NO).TSize; -end; +end %Find ROI's for loop=1:length(roinames) @@ -298,15 +297,15 @@ if ~isnan(temp) if isnan(roivolume(zloop,tloop)) roivolume(zloop,tloop) = 0; - end; + end roivolume(zloop,tloop) = roivolume(zloop,tloop)+temp; - end; + end end - end; - end; - end; - end; - end; + end + end + end + end + end %Export ROI volume temp = roivolume; @@ -316,16 +315,16 @@ for tloop=1:SET(NO).TSize outdata{rowoffset,tloop+coloffset} = sprintf('%s:TF%d',roinames{loop},tloop); outdata{6+loop,1+tloop} = temp(tloop); - end; + end for zloop=1:SET(NO).ZSize for tloop=1:SET(NO).TSize outdata{rowoffset+zloop,tloop+coloffset} = roivolume(zloop,tloop); - end; - end; + end + end %Increae column offset coloffset = coloffset+SET(NO).TSize; -end; +end segment('cell2clipboard',outdata); @@ -337,15 +336,15 @@ for tloop=1:SET(NO).TSize outdata{rowoffset,tloop+coloffset} = sprintf('%s:TF%d',type,tloop); -end; +end for zloop=1:SET(NO).ZSize for tloop=1:SET(NO).TSize outdata{rowoffset+zloop,tloop+coloffset} = (SET(NO).SliceThickness+SET(NO).SliceGap)*stablepolyarea(... SET(NO).ResolutionY*y(1:end-1,tloop,zloop),... SET(NO).ResolutionX*x(1:end-1,tloop,zloop))/1000; - end; -end; + end +end %------------------------------ function exportcontour_Callback %#ok @@ -358,7 +357,7 @@ if isempty(x) myfailed('User aborted or no contour available.',DATA.GUI.Segment); return; -end; +end %Find slices with contour totinslice = size(x,1)*size(x,2); @@ -385,19 +384,19 @@ for tloop=1:size(x,2) outdata{4,2+2*(tloop-1)} = sprintf('X_tf%02d',tloop); outdata{4,3+2*(tloop-1)} = sprintf('Y_tf%02d',tloop); -end; +end for zloop=1:length(slices) %write slice number for nloop=1:size(x,1) outdata{4+(zloop-1)*size(x,1)+nloop,1} = slices(zloop); - end; + end for tloop=1:size(x,2) for nloop=1:size(x,1) outdata{4+(zloop-1)*size(x,1)+nloop,2+2*(tloop-1)} = SET(NO).ResolutionX*x(nloop,tloop,slices(zloop)); outdata{4+(zloop-1)*size(x,1)+nloop,3+2*(tloop-1)} = SET(NO).ResolutionY*y(nloop,tloop,slices(zloop)); - end; - end; -end; + end + end +end segment('cell2clipboard',outdata); @@ -416,42 +415,42 @@ function exportimage_Callback(image2store) %#ok if yesno('Several images selected. Export all?') multipleslices = true; templatename = 'image_slice000'; - end; - end; -end; + end + end +end try - temppwd = pwd; + temppwd = DATA.SegmentFolder; if exist(DATA.Pref.exportpath,'dir') cd(DATA.Pref.exportpath); else mydisp('Warning: Export path does not exist, please check preferences.'); - end; + end [filename, pathname,filterindex] = myuiputfile(... { '*.png','PNG image (*.png)';... '*.jpg','JPEG image (*.jpg)';... '*.bmp','BMP image (*.bmp)';... '*.tif','TIFF image (*.tif)'},... - 'Save file as',templatename); + dprintf('Save file as'),templatename); cd(temppwd); if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); +% myfailed('Operation cancelled.',DATA.GUI.Segment); return; - end; + end if multipleslices filename = removenumerics(filename); slices = SET(no).StartSlice:SET(no).EndSlice; else slices = SET(no).CurrentSlice; - end; + end if multipleslices h = waitbar(0,'Please wait.'); - end; - for loop = 1:length(slices); + end + for loop = 1:length(slices) %Get the image if nargin < 1 @@ -463,12 +462,12 @@ function exportimage_Callback(image2store) %#ok imxsz = SET(no).XSize*scale; imysz = SET(no).YSize*scale; image2store = imresize(image2store,[imxsz imysz],'bilinear'); - end; + end image2store = calcfunctions('remapuint8viewim',image2store,no); else image2store = squeeze(DATA.ViewIM{DATA.CurrentPanel}(:,:,SET(no).CurrentTimeFrame,:)); - end; + end end %Add extension if necessary @@ -478,7 +477,7 @@ function exportimage_Callback(image2store) %#ok f = fullfile(pathname,sprintf('%s%03d',filename,slices(loop))); else f = fullfile(pathname,filename); - end; + end switch filterindex case 1 @@ -489,7 +488,7 @@ function exportimage_Callback(image2store) %#ok f = [f '.bmp']; %#ok case 4 f = [f '.tif']; %#ok - end; + end switch filterindex case 1 @@ -501,17 +500,17 @@ function exportimage_Callback(image2store) %#ok imwrite(image2store,f,'bmp'); case 4 imwrite(image2store,f,'tif'); - end; + end if multipleslices waitbar(loop/length(slices),h); - end; + end - end; %Loop over slices (either only one or many) + end %Loop over slices (either only one or many) if multipleslices close(h); - end; + end catch me mydispexception(me); @@ -529,158 +528,28 @@ function exportimage_Callback(image2store) %#ok %Remove numbers from a filename stri = stri( (stri<47) | (stri>57) ); + %--------------------------- function screenshot_Callback %#ok %--------------------------- %Create an image file of a screenshot of the main axis -global DATA SET +global DATA -temp = pwd; -if exist(DATA.Pref.exportpath,'dir') - cd(DATA.Pref.exportpath); +temp = DATA.SegmentFolder; +if ~DATA.isSiemensVersion + if exist(DATA.Pref.exportpath,'dir') + cd(DATA.Pref.exportpath); + else + mydisp('Warning: Export path does not exist, please check preferences.'); + end else - mydisp('Warning: Export path does not exist, please check preferences.'); -end; - -m = mymenu('Save to file or to PACS?','Save to file','Save to PACS',... - 'Save for inclusion in report'); + % allowed path in open apps + cd('\\tsclient\c'); +end +cropscreenshot +cd(temp) -switch m - case 1 - [filename, pathname,filterindex] = myuiputfile(... - { '*.png','PNG image (*.png)';... - '*.jpg','JPEG image (*.jpg)';... - '*.bmp','BMP image (*.bmp)';... - '*.tif','TIFF image (*.tif)'},... - 'Save file as','screenshot'); - case 2 - filename = 'screenshot.dcm'; - pathname = getpreferencespath; - filterindex = 5; - case 3 - name = removeforbiddenchars(SET(1).PatientInfo.Name); - if isempty(name) - name = 'Hidden'; - end; - pathname = fullfile(DATA.Pref.Pacs.ReportsheetPath, ... - name,'Screenshots'); - if ~exist(pathname,'dir') - sucess = mkdir(pathname); - if ~sucess - myfailed('Could not create screenshot directory. Aborted'); - return - end - end - reportdir = dir(fullfile(pathname,'screenshot*.png')); - nbrs = zeros(1,numel(reportdir)); - for i = 1:numel(reportdir) - nbrs(i) = sscanf(reportdir(i).name(12:15),'%f'); - end - newnbr = min(setdiff(1:9999,nbrs)); - filename = sprintf('screenshot_%04.0f.png',newnbr); - filterindex = 1; - DATA.Pref.Pacs.ScreenshotPath=pathname; - case 0 - filename = 0; -end - -cd(temp); -set(DATA.Handles.screenshoticon,'state','off'); -if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); - return; -end; -h = DATA.Handles.imageaxes(DATA.CurrentPanel); -frame = mygetframe(h); -im = frame2im(frame); -f = fullfile(pathname,filename); - -%Add extension if necessary -[~,~,ext] = fileparts(f); -if isempty(ext) - switch filterindex - case 1 - f = [f '.png']; - case 2 - f = [f '.jpg']; - case 3 - f = [f '.bmp']; - case 4 - f = [f '.tif']; - case 5 - f = [f '.dcm']; - end; -end; - -switch filterindex - case 1 - try - imwrite(im,f,'png','bitdepth',8,'software','Segment',... - 'creationtime',datestr(now)); - mydisp('Export successful'); - catch - mydisp('Export failed'); - end - case 2 - try - imwrite(im,f,'jpg','quality',100); - mydisp('Export successful'); - catch - mydisp('Export failed'); - end - case 3 - try - imwrite(im,f,'bmp'); - mydisp('Export successful'); - catch - mydisp('Export failed'); - end - case 4 - try - imwrite(im,f,'tif'); - mydisp('Export successful'); - catch - mydisp('Export failed'); - end - - case 5 - makeimagedicom(im,f,DATA.ViewPanels(DATA.CurrentPanel)); - try - successful=pacs('savetopacs_helper',{f},getpreferencespath); - catch me - successful=0; - mydispexception(me); - myfailed(me.message); - end - try - status=1; - delete(f) - catch - status=0; - end - - stri=''; - if successful - stri='Save to PACS success'; - else - stri='Save to PACS failed'; - end - - if status==1 - stri=[stri,' and succesfully removed report from computer.']; - else - stri=[stri,' and failed to remove report from computer.']; - end - - mydisp(translation.dictionary(stri)) -end; -%catch -% myfailed('Export of image failed.'); -% return; -%end - -%mymsgbox('Export successful.','Done!'); %-------------------------------------------------------- function ok = exportsavemovie(mov,left,right,up,down,fps) @@ -698,28 +567,28 @@ function exportimage_Callback(image2store) %#ok epath = DATA.Pref.exportpath; else mydisp('Warning: Export path does not exist, please check preferences.'); - epath = pwd; -end; + epath = DATA.SegmentFolder; +end if nargin<2 left = 1; -end; +end if nargin<3 right = size(mov(1).cdata,2); -end; +end if nargin<4 up = 1; -end; +end if nargin<5 down = size(mov(1).cdata,2); -end; +end if nargin<6 fps = 15; -end; +end ok = false; %Pessimistic @@ -737,17 +606,17 @@ function exportimage_Callback(image2store) %#ok if isequal(m,0) myfailed('User pressed cancel',DATA.GUI.Segment); return; - end; + end [filename, pathname] = myuiputfile(... '*.avi',... - 'Save avi-file as',... + dprintf('Save file as'),... fullfile(epath,'movie.avi')); if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); +% myfailed('Operation cancelled.',DATA.GUI.Segment); return; - end; + end %Set the compressor switch m @@ -761,7 +630,7 @@ function exportimage_Callback(image2store) %#ok profile = 'Archival'; otherwise profile = 'None'; - end; + end %Open the file fid = VideoWriter(fullfile(pathname,filename), profile); @@ -771,15 +640,14 @@ function exportimage_Callback(image2store) %#ok %Add frames myworkon; h = mywaitbarstart(length(mov),'Please wait, storing movie.'); - myadjust(h.h,DATA.GUI.Segment); for loop=1:length(mov) temp = mov(loop).cdata; if nargin>1 temp = temp(up:down,left:right,:); %EH: 2009-08-31 - end; + end fid.writeVideo(temp); h = mywaitbarupdate(h); - end; + end mywaitbarclose(h); myworkoff; @@ -790,7 +658,7 @@ function exportimage_Callback(image2store) %#ok %png-files [filename, pathname] = myuiputfile(... '*.*',... - 'Save files as',... + dprintf('Save files as'),... [epath filesep 'im']); handles.filename = fullfile(pathname,filename); [pathname,filename] = fileparts(handles.filename); @@ -798,15 +666,14 @@ function exportimage_Callback(image2store) %#ok myworkon; h = mywaitbarstart(length(mov),'Please wait, storing movie.'); - myadjust(h.h,DATA.GUI.Segment.fig) for loop=1:length(mov) [temp] = frame2im(mov(loop)); if nargin>1 temp = temp(up:down,left:right,:); - end; + end imwrite(temp,[handles.filename sprintf('%05d.png',loop)],'png'); h = mywaitbarupdate(h); - end; + end mywaitbarclose(h); myworkoff; case 3 @@ -815,20 +682,20 @@ function exportimage_Callback(image2store) %#ok %Select filename [filename, pathname] = myuiputfile(... '*.gif',... - 'Save animated gif-file as',... + dprintf('Save file as'),... fullfile(epath,'movie.gif')); if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); +% myfailed('Operation cancelled.',DATA.GUI.Segment); return; - end; + end dither = yesno('Do you want to use dithering for better colormap?'); if dither ditherstring = 'dither'; else ditherstring = 'nodither'; - end; + end myworkon; h = mywaitbarstart(length(mov),'Please wait, storing movie.'); @@ -842,12 +709,12 @@ function exportimage_Callback(image2store) %#ok im(1,1,1,length(mov)) = 0; %Reserve memory else im(:,:,1,loop) = rgb2ind(imrgb,map,ditherstring); - end; + end h = mywaitbarupdate(h); - end; + end - imwrite(im,map,[pathname filesep filename],'DelayTime',0,'LoopCount',inf) %g443800 + imwrite(im,map,[pathname filesep filename],'DelayTime',1/fps,'LoopCount',inf) %g443800 mywaitbarclose(h); myworkoff; @@ -855,7 +722,7 @@ function exportimage_Callback(image2store) %#ok otherwise myfailed('Saving aborted.',DATA.GUI.Segment); return; -end; +end ok = true; @@ -873,18 +740,13 @@ function exportmovierecorder_Callback(arg) if SET(NO).TSize==1 myfailed('Need more than one timeframe to record movie.',DATA.GUI.Segment); return; - end; - - set(DATA.Handles.movierecordericon,'state','off'); + end - fig = openfig('movierecorder.fig','reuse'); - myadjust(fig,DATA.GUI.Segment); - blockfig(fig); - set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); + fig = mygui('movierecorder.fig'); % Generate a structure of handles to pass to callbacks, and store it. - handles = guihandles(fig); - handles.fig = fig; + handles = fig.handles; + handles.fig = handles.figure1; handles.recording = false; handles.frames = SET(NO).TSize; handles.fps = 15; @@ -892,6 +754,7 @@ function exportmovierecorder_Callback(arg) handles.crop = false; handles.size = []; DATA.Record = true; + myadjust(handles.fig,DATA.GUI.Segment); axis(handles.previewaxes,'off'); set(handles.framesedit,'string',sprintf('%d',handles.frames)); mymsgbox([... @@ -908,7 +771,7 @@ function exportmovierecorder_Callback(arg) set(handles.fpsedit,'String',sprintf('%d',handles.fps)); myfailed('Could not interpret number.',handles.fig); return; - end; + end handles.fps = temp; set(handles.fpsedit,'String',sprintf('%d',handles.fps)); case 'frames' @@ -918,7 +781,7 @@ function exportmovierecorder_Callback(arg) set(handles.framesedit,'String',sprintf('%d',handles.frames)); myfailed('Could not interpret number.',handles.fig); return; - end; + end handles.frames = temp; set(handles.framesedit,'String',sprintf('%d',handles.frames)); case 'newframe' @@ -937,19 +800,19 @@ function exportmovierecorder_Callback(arg) else handles.storedframes = handles.storedframes+1; handles.movie(handles.storedframes) = DATA.MovieFrame; - end; - mydisp(dprintf('Frame %d stored.',handles.storedframes)); - end; + end + mydisp(sprintf('Frame %d stored.',handles.storedframes)); + end if handles.storedframes==handles.frames exportmovierecorder_Callback('store'); return; - end; - end; + end + end case 'crop' if isempty(handles.size) myfailed('No preview available.',handles.fig); return; - end; + end mymsgbox('Click in the upper-left corner and the bottom-right corner to set crop limits.',''); [x,y] = ginput(2); hold(handles.previewaxes,'on'); @@ -979,7 +842,7 @@ function exportmovierecorder_Callback(arg) DATA.Record = false; if handles.storedframes>1 exportmovierecorder_Callback('store'); - end; + end case 'store' mydisp('Storing movie to disc.'); if not(handles.crop) @@ -993,15 +856,25 @@ function exportmovierecorder_Callback(arg) handles.up = max(handles.up,1); handles.down = min(handles.down,handles.size(1)); handles.crop = true; - end; + end ok = exportsavemovie(handles.movie,handles.left,handles.right,handles.up,handles.down,handles.fps); if ~ok myfailed('Export of movie failed.',handles.fig); return; - end; + end handles.movie = []; handles.storedframes = 0; DATA.Record = false; + + if ~isempty(DATA.GUI.StrainTagging) %to turn off Play button in Strain Window + gui = DATA.GUI.StrainTagging; + set(gui.handles.playtogglebutton,'Value',0); + gui.run = 0; + elseif ~isempty(DATA.GUI.Segment) + DATA.Run = 0; + undent(DATA.Handles.permanenticonholder,'play',0) + end + case 'close' DATA.Record = false; close(handles.fig); @@ -1009,8 +882,8 @@ function exportmovierecorder_Callback(arg) otherwise myfailed(dprintf('Unknown option %s for exportmovierecorder',arg),handles.fig); return; - end; -end; + end +end %--------------------------- function exportmovie_Callback %#ok @@ -1031,13 +904,13 @@ function exportmovierecorder_Callback(arg) mov(tloop) = im2frame(temp); %#ok else mov(tloop) = im2frame(temp,SET(NO).Colormap); %#ok - end; + end h = mywaitbarupdate(h); -end; +end mywaitbarclose(h); if ~DATA.Testing - s = inputdlg({'Number of frames per second'},'fps',1,{sprintf('%d',15)}); + s = myinputdlg({'Number of frames per second'},'fps',1,{sprintf('%d',15)}); else s{1} = popfrombuffer('String'); end @@ -1049,8 +922,8 @@ function exportmovierecorder_Callback(arg) if not(ok) myfailed('Invalid fps.',DATA.GUI.Segment); return; - end; -end; + end +end %Call to save to disk ok = exportsavemovie(mov,1,size(temp,2),1,size(temp,1),fps); @@ -1058,7 +931,7 @@ function exportmovierecorder_Callback(arg) if ok mymsgbox('Export successful.','Done!'); -end; +end %---------------------------------- function exportvolumecurve_Callback %#ok @@ -1081,7 +954,7 @@ function exportmovierecorder_Callback(arg) SET(NO).RVV(loop),... SET(NO).RVEPV(loop))... ]; %#ok -end; +end clipboard('copy',stri); mymsgbox('Results copied to clipboard','Done!'); @@ -1103,7 +976,7 @@ function exportmovierecorder_Callback(arg) sprintf('%s\t%f\t%f\n',... SET(no).ImageViewPlane, spacedist, timedist) ... ]; %#ok -end; +end clipboard('copy',stri); mymsgbox('Results copied to clipboard','Done!'); @@ -1118,7 +991,7 @@ function exportmovierecorder_Callback(arg) if isempty(SET(NO).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end % Ask user for directory and filename [outfile, outdir] = myuiputfile; @@ -1130,28 +1003,28 @@ function exportmovierecorder_Callback(arg) y = SET(NO).EndoY; z = (0:size(x,3)-1); matlab2ensightgolddeformingmesh(outdir, outfile, 'Endo', x, y, z, timesteps); -end; +end if not(isempty(SET(NO).EpiX)) x = SET(NO).EpiX; y = SET(NO).EpiY; z = (0:size(x,3)-1); matlab2ensightgolddeformingmesh(outdir, outfile, 'Epi', x, y, z, timesteps); -end; +end if not(isempty(SET(NO).RVEndoX)) x = SET(NO).RVEndoX; y = SET(NO).RVEndoY; z = (0:size(x,3)-1); matlab2ensightgolddeformingmesh(outdir, outfile, 'RVEndo', x, y, z, timesteps); -end; +end if not(isempty(SET(NO).RVEpiX)) x = SET(NO).RVEpiX; y = SET(NO).RVEpiY; z = (0:size(x,3)-1); matlab2ensightgolddeformingmesh(outdir, outfile, 'RVEpi', x, y, z, timesteps); -end; +end %--------------------------------- function exportlv2ensight_Callback %#ok @@ -1163,7 +1036,7 @@ function exportmovierecorder_Callback(arg) if isempty(SET(NO).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end % Started by Einar Heiberg (?) % Seriously by Johannes Toger Jan 20, 2009 @@ -1264,7 +1137,7 @@ function exporttoclipboardthisstack_Callback(doheader) %#ok if nargin<1 doheader = false; -end; +end exporttoclipboard_Callback(doheader,NO); @@ -1274,7 +1147,7 @@ function exporttoclipboard_Callback(doheader,no) %Export data to clipboard. Calls another function to do the export. if nargin==0 doheader = true; -end; +end includenormalized = yesno('Do you want to include BSA normalized values?'); @@ -1282,7 +1155,7 @@ function exporttoclipboard_Callback(doheader,no) exportdata(doheader,includenormalized); else exportdata(doheader,includenormalized,no); -end; +end %--------------------------------------- function [outdata,ind] = header(onlyone) @@ -1292,7 +1165,7 @@ function exporttoclipboard_Callback(doheader,no) outdata{1, 1} = 'FileName'; else outdata{1, 1} = 'ImageStack'; -end; +end outdata{1, 2} = 'PatientName'; outdata{1, 3} = 'PatientID'; outdata{1, 4} = 'AcquisitionDate'; @@ -1357,7 +1230,9 @@ function exporttoclipboard_Callback(doheader,no) outdata{1,62} = 'RVPER[ml/s]'; outdata{1,63} = 'LVM measured at ED'; outdata{1,64} = 'LVM measured at ES'; - +outdata{1,65} = 'qCS-stress [ml/min / LVM]'; +outdata{1,66} = 'qCS-rest [ml/min / LVM]'; +outdata{1,67} = 'CS-MPR'; ind = [9 14 16 18 20 23 28 30 32 34]; @@ -1384,9 +1259,9 @@ function exportmultiple_Callback(dosegdicom) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -1395,7 +1270,7 @@ function exportmultiple_Callback(dosegdicom) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end includenormalized = yesno('Do you want to include BSA normalized values?'); @@ -1406,7 +1281,7 @@ function exportmultiple_Callback(dosegdicom) %#ok %--- Write header for loop=1:length(temp) outdata{1,loop} = temp{loop}; -end; +end %Loop over all files numrows=1; @@ -1416,7 +1291,7 @@ function exportmultiple_Callback(dosegdicom) %#ok %--- Load file DATA.Silent = true; %Turn on "silent" mode to avoid to much update on screen when loading etc. - disp(dprintf('Loading %s.',files2load(fileloop).name)); %#ok + disp(dprintf('Loading %s.',files2load(fileloop).name)); %Set filename outdata{numrows+1,1} = files2load(fileloop).name; @@ -1452,10 +1327,10 @@ function exportmultiple_Callback(dosegdicom) %#ok temp = exportdata(false,true); %false means no header; true normalized will be removed later %Copy the data - for col=2:size(temp,2); - for row=1:size(temp,1); + for col=2:size(temp,2) + for row=1:size(temp,1) outdata{numrows+row,col} = temp{row,col}; - end; + end end numrows=numrows+size(temp,1); @@ -1466,14 +1341,14 @@ function exportmultiple_Callback(dosegdicom) %#ok outdata{fileloop+1,2} = 'FAILED.'; end h = mywaitbarupdate(h); -end; %loop over files +end %loop over files mywaitbarclose(h); %If not wanted remove non normalized values. ind = true(1,size(outdata,2)); if ~includenormalized ind(indforbsa) = false; -end; +end outdata = outdata(:,ind); %--- Output to a string @@ -1508,9 +1383,9 @@ function exportmultipleROI_Callback(dosegdicom) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -1519,7 +1394,7 @@ function exportmultipleROI_Callback(dosegdicom) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end %Store current work SET oldSET=SET; @@ -1552,14 +1427,15 @@ function exportmultipleROI_Callback(dosegdicom) %#ok % outdata{1,10} = 'HeartRate[bpm]'; outdata{1, 1}= 'FileName'; outdata{1, 2}= 'Stack number'; -outdata{1, 3}= 'ImageViewPlane'; -outdata{1, 4}= 'RoiName'; -outdata{1, 5}= 'Mean Area'; -outdata{1, 6}= 'Min Area'; -outdata{1, 7}= 'Max Area'; -outdata{1, 8}= 'Mean'; -outdata{1, 9}= 'StD'; -outdata{1, 10}= 'Flow'; +outdata{1, 3}= 'Image Type'; +outdata{1, 4}= 'Image View Plane'; +outdata{1, 5}= 'RoiName'; +outdata{1, 6}= 'Mean Area'; +outdata{1, 7}= 'Min Area'; +outdata{1, 8}= 'Max Area'; +outdata{1, 9}= 'Mean'; +outdata{1, 10}= 'StD'; +outdata{1, 11}= 'Flow'; %Loop over all files @@ -1570,10 +1446,7 @@ function exportmultipleROI_Callback(dosegdicom) %#ok %--- Load file DATA.Silent = true; %Turn on "silent" mode to avoid to much update on screen when loading etc. - disp(dprintf('Loading %s.',files2load(fileloop).name)); %#ok - - %Set filename - outdata{numrows+1,1} = files2load(fileloop).name; + disp(dprintf('Loading %s.',files2load(fileloop).name)); SET = []; % %Make sure a fresh start @@ -1607,17 +1480,19 @@ function exportmultipleROI_Callback(dosegdicom) %#ok names={}; Rois=Rois(sortind); if ~(length(Rois)==1 && isempty(Rois(1).X)) - outdata{numrows+1,2}=no; - outdata{numrows+1,3}=SET(no).ImageViewPlane; - for roi=Rois - outdata{numrows+1,4}=roi.Name; - outdata{numrows+1,5}=nanmean(roi.Area); - outdata{numrows+1,6}=min(roi.Area); - outdata{numrows+1,7}=max(roi.Area); - outdata{numrows+1,8}=nanmean(roi.Mean); - outdata{numrows+1,9}=nanmean(roi.StD); + for roi=Rois + outdata{numrows+1,1} = files2load(fileloop).name; + outdata{numrows+1,2}=no; + outdata{numrows+1,3}=SET(no).ImageType; + outdata{numrows+1,4}=SET(no).ImageViewPlane; + outdata{numrows+1,5}=roi.Name; + outdata{numrows+1,6}=nanmean(roi.Area); + outdata{numrows+1,7}=min(roi.Area); + outdata{numrows+1,8}=max(roi.Area); + outdata{numrows+1,9}=nanmean(roi.Mean); + outdata{numrows+1,10}=nanmean(roi.StD); if isfield(roi, 'Flow') && ~isempty(roi.Flow) - outdata{numrows+1,10}=nanmean(roi.Flow.meanflow); + outdata{numrows+1,11}=nanmean(roi.Flow.meanflow); end numrows=numrows+1; end @@ -1640,7 +1515,7 @@ function exportmultipleROI_Callback(dosegdicom) %#ok outdata{numrows+1,2} = 'FAILED.'; end h = mywaitbarupdate(h); -end; %loop over files +end %loop over files mywaitbarclose(h); %If not wanted remove non normalized values. @@ -1674,9 +1549,9 @@ function exportmultipleROI_Callback(dosegdicom) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep '*.mat']); @@ -1685,7 +1560,7 @@ function exportmultipleROI_Callback(dosegdicom) %#ok if numfiles==0 myfailed('Found no files to export information about.',DATA.GUI.Segment); return; -end; +end %Create output matrix nbrdataperstack = 19; @@ -1699,7 +1574,7 @@ function exportmultipleROI_Callback(dosegdicom) %#ok %--- Load file DATA.Silent = true; %Turn on "silent" mode to avoid to much update on screen when loading etc. - disp(dprintf('Loading %s.',files2load(fileloop).name)); %#ok + disp(dprintf('Loading %s.',files2load(fileloop).name)); %Set filename outdata{fileloop+1,1} = files2load(fileloop).name; @@ -1727,17 +1602,17 @@ function exportmultipleROI_Callback(dosegdicom) %#ok isscar = 'NO'; else isscar = 'YES'; - end; + end if isempty(SET(sloop).Flow) isflow = 'NO'; else isflow = 'YES'; - end; + end if isempty(SET(sloop).EndoX)&&isempty(SET(sloop).EpiX) isseg = 'NO'; else isseg = 'YES'; - end; + end coloffset = 1+(sloop-1)*nbrdataperstack; row = fileloop+1; outdata{row, 1+coloffset} = SET(sloop).ImageType; @@ -1759,14 +1634,14 @@ function exportmultipleROI_Callback(dosegdicom) %#ok outdata{row,17+coloffset} = SET(sloop).RepetitionTime; outdata{row,18+coloffset} = num2str(SET(sloop).InversionTime); outdata{row,19+coloffset} = SET(sloop).HeartRate; - end; + end %catch % %--- Some thing went wrong % outdata{fileloop+1,2} = 'FAILED.'; %end h = mywaitbarupdate(h); -end; %loop over files +end %loop over files mywaitbarclose(h); %--- Write header @@ -1792,7 +1667,7 @@ function exportmultipleROI_Callback(dosegdicom) %#ok outdata{row,17+coloffset} = 'RepetitionTime'; outdata{row,18+coloffset} = 'InversionTime'; outdata{row,19+coloffset} = 'HeartRate'; -end; +end %--- Output to a string segment('cell2clipboard',outdata); @@ -1830,9 +1705,9 @@ function exportmultiplestraingraphs_Callback(type) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -1841,7 +1716,7 @@ function exportmultiplestraingraphs_Callback(type) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end % do strain? output=questdlg('Do you wish to redo strain analysis?'); @@ -1905,7 +1780,7 @@ function exportmultiplestraingraphs_Callback(type) %#ok disp('Unknown image view plane'); end - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -1946,7 +1821,7 @@ function exportmultiplestraingraphs_Callback(type) %#ok %Skip no else - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -2020,7 +1895,7 @@ function exportmultiplestraingraphs_Callback(type) %#ok outdata{line+2,1} = 'Heart Rate'; outdata{line+3,1} = 'Image Type'; - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -2033,8 +1908,8 @@ function exportmultiplestraingraphs_Callback(type) %#ok %aha sections for loop=1:17 [stri,pos] = reportbullseye('aha17nameandpos',loop); %Get name and position of export - outdata{line+8+loop,radcol} = stri; - outdata{line+8+loop,circcol} = stri; + outdata{line+8+pos,radcol} = stri; + outdata{line+8+pos,circcol} = stri; end outdata{line+7,1} = 'Radial strain'; if strcmp(SET(no).ImageViewPlane,'Short-axis') @@ -2052,7 +1927,7 @@ function exportmultiplestraingraphs_Callback(type) %#ok else %currently used slices cus=[]; - for tagno=SET(no).StrainTagging.taggroup; + for tagno=SET(no).StrainTagging.taggroup cus=[cus, ' ', SET(tagno).ImageViewPlane]; end outdata{line+3,2} = sprintf('%s %s',SET(no).ImageType,cus); @@ -2176,7 +2051,7 @@ function exportmultiplestraingraphs_Callback(type) %#ok %line = line+1; % end end - end; %loop over image stack + end %loop over image stack if doStrain %store file @@ -2231,6 +2106,8 @@ function exportmultiplestrain_Callback(type) %#ok global DATA SET NO +doTaggroup = true; % Correct issue with taggroup if any long-axis image have been deleted from the file + suffix = 'mat'; %Ask if wnat to save before closing current image stack @@ -2247,9 +2124,9 @@ function exportmultiplestrain_Callback(type) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -2258,7 +2135,7 @@ function exportmultiplestrain_Callback(type) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end % do strain? output=questdlg('Do you wish to redo strain analysis?'); @@ -2317,6 +2194,41 @@ function exportmultiplestrain_Callback(type) %#ok bullseyeradial = cell(1,1); bullseyecirc = cell(1,1); for no=1:length(SET) + + if doTaggroup && isfield(SET(no),'StrainTagging') && not(isempty(SET(no).StrainTagging)) + + switch SET(no).ImageViewPlane + case 'Short-axis' + imageviewplane = 'shortaxis'; + case {'2CH','3CH','4CH'} + imageviewplane = 'longaxis'; + otherwise + disp('Unknown image view plane'); + imageviewplane = []; + end + + switch SET(no).ImageType + case {'Cine', 'Feature tracking'} + imagetype='cine'; + case 'Strain from tagging' + imagetype='tagging'; + end + + if isequal(type,imagetype) && isequal(imageviewplane,'longaxis') + temptaggroup=straintagging.straintagging('findtaggroup',type,1); + taggroup = []; + for i = temptaggroup + if isfield(SET(i).StrainTagging,'peaktf') + taggroup = [taggroup i]; + else + end + end + for i = temptaggroup + SET(i).StrainTagging.taggroup = taggroup; + end + end + + end if doStrain if ~isfield(SET(no),'StrainTagging') || isempty(SET(no).StrainTagging)||~isfield(SET(no).StrainTagging,'taggroup') ||~isfield(SET(no).StrainTagging,'transformparameters') || ismember(no,checked) || isempty(SET(no).EndoX) || all(isnan(SET(no).EndoX(:))) %Skip this no @@ -2337,12 +2249,13 @@ function exportmultiplestrain_Callback(type) %#ok case 'Short-axis' imageviewplane = 'shortaxis'; case {'2CH','3CH','4CH'} - imageviewplane = 'longaxis'; + imageviewplane = 'longaxis'; otherwise disp('Unknown image view plane'); + imageviewplane = []; end - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -2351,11 +2264,11 @@ function exportmultiplestrain_Callback(type) %#ok if isequal(type,imagetype) taggroup=straintagging.straintagging('findtaggroup',type,1); - for i = taggroup; - if ~isfield(SET(i).StrainTagging,'taggroup') - SET(i).StrainTagging.taggroup = taggroup; - end + for i = taggroup + if ~isfield(SET(i).StrainTagging,'taggroup') + SET(i).StrainTagging.taggroup = taggroup; end + end NO=no; SET(no).StrainTagging.LVupdated=1; @@ -2406,7 +2319,7 @@ function exportmultiplestrain_Callback(type) %#ok %Skip no else - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -2449,7 +2362,7 @@ function exportmultiplestrain_Callback(type) %#ok %--- output --- %patient info outdata{line,1} = 'Patient name'; - outdata{line,2} = 'Patient ID'; + outdata{line,2} = 'Patient ID'; % 'Filename'; outdata{line,3} = 'Heart Rate'; outdata{line,4} = 'Image Type'; %global strain values @@ -2482,7 +2395,7 @@ function exportmultiplestrain_Callback(type) %#ok end line = line+1; - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -2491,7 +2404,7 @@ function exportmultiplestrain_Callback(type) %#ok %if isequal(type,imagetype) outdata{line,1} = SET(no).PatientInfo.Name; - outdata{line,2} = SET(no).PatientInfo.ID; + outdata{line,2} = SET(no).PatientInfo.ID; %files2load(fileloop).name; outdata{line,3} = SET(no).HeartRate; outdata{line,4} = sprintf('%s %s',SET(no).ImageType,SET(no).ImageViewPlane); @@ -2727,73 +2640,76 @@ function exportmultiplestrain_Callback(type) %#ok %slice based export of strain and strain rate - col = 44; - % nbrslices = length(SET(no).StrainTagging.saslices); + %col = 44; + % nbrslices = length(SET(no).StrainTagging.saslices); outdata{line-2,col} = 'Peak radial strain [%]'; %for sliceloop = 1:nbrslices - %outdata{line-1,col} = sprintf('Slice %d',sliceloop); - outdata{line,col} = SET(no).StrainTagging.globalrad(SET(no).StrainTagging.peaktf,1); - col = col+1; - % end + %outdata{line-1,col} = sprintf('Slice %d',sliceloop); + outdata{line,col} = SET(no).StrainTagging.globalrad(SET(no).StrainTagging.peaktf,1); + col = col+1; + % end outdata{line-2,col} = 'Peak longit. strain [%]'; %for sliceloop = 1:nbrslices - %outdata{line-1,col} = sprintf('Slice %d',sliceloop); - outdata{line,col} = SET(no).StrainTagging.globalcirc(SET(no).StrainTagging.peaktf,1); - col = col+1; + %outdata{line-1,col} = sprintf('Slice %d',sliceloop); + outdata{line,col} = SET(no).StrainTagging.globalcirc(SET(no).StrainTagging.peaktf,1); + col = col+1; %end - if isfield(SET(no).StrainTagging,'SR') && any(SET(no).StrainTagging.SR.include) - outdata{line-2,col} = 'Radial strain rate [%/s]'; - %ind=find(SET(no).StrainTagging.taggroup==no); - switch SET(no).ImageViewPlane - case '2CH' - if SET(no).StrainTagging.SR.include(1) - ind=1; - end - case '3CH' - if SET(no).StrainTagging.SR.include(2) - if any(strcmp({SET(SET(no).StrainTagging.taggroup).ImageViewPlane},'4CH')) - ind=length(SET(no).StrainTagging.taggroup)-1; - else - ind=length(SET(no).StrainTagging.taggroup); - end - end - case '4CH' - if SET(no).StrainTagging.SR.include(3) - ind=length(SET(no).StrainTagging.taggroup); - end - otherwise - ind=[]; - end - - if ~isempty(ind) - outdata{line-1,col} = 'Upslope'; - outdata{line,col} = SET(no).StrainTagging.SR.radup(ind);%SET(no).StrainTagging.upsloperad(1,1); - outdata{line-1,col+1} = 'Upslope time'; - outdata{line,col+1} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.radupind(ind));%StrainTagging.upsloperad(1,2); - outdata{line-1,col+2} = 'Downslope'; - outdata{line,col+2} = SET(no).StrainTagging.SR.raddown(ind);%SET(no).StrainTagging.downsloperad(1,1); - outdata{line-1,col+3} = 'Downslope time'; - outdata{line,col+3} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.raddownind(ind));%SET(no).StrainTagging.downsloperad(1,2); - col = col+4; - outdata{line-2,col} = 'Longit. strain rate [%/s]'; - outdata{line-1,col} = 'Upslope'; - outdata{line,col} = SET(no).StrainTagging.SR.circup(ind);%SET(no).StrainTagging.upslopecircum(1,1); - outdata{line-1,col+1} = 'Upslope time'; - outdata{line,col+1} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.circupind(ind));%SET(no).StrainTagging.upslopecircum(1,2); - outdata{line-1,col+2} = 'Downslope'; - outdata{line,col+2} = SET(no).StrainTagging.SR.circdown(ind);%SET(no).StrainTagging.downslopecircum(1,1); - outdata{line-1,col+3} = 'Downslope time'; - outdata{line,col+3} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.circdownind(ind));%SET(no).StrainTagging.downslopecircum(1,2); - col = col+4; - line=line+3; - end + if isfield(SET(no).StrainTagging,'SR') && any(SET(no).StrainTagging.SR.include) + outdata{line-2,col} = 'Radial strain rate [%/s]'; + %ind=find(SET(no).StrainTagging.taggroup==no); + if not(isfield(SET(no).StrainTagging,'taggroup')) + SET(no).StrainTagging.taggroup=straintagging.straintagging('findtaggroup',imagetype); + end + switch SET(no).ImageViewPlane + case '2CH' + if SET(no).StrainTagging.SR.include(1) + ind=1; + end + case '3CH' + if SET(no).StrainTagging.SR.include(2) + if any(strcmp({SET(SET(no).StrainTagging.taggroup).ImageViewPlane},'4CH')) + ind=length(SET(no).StrainTagging.taggroup)-1; + else + ind=length(SET(no).StrainTagging.taggroup); + end + end + case '4CH' + if SET(no).StrainTagging.SR.include(3) + ind=length(SET(no).StrainTagging.taggroup); + end + otherwise + ind=[]; + end + + if ~isempty(ind) + outdata{line-1,col} = 'Upslope'; + outdata{line,col} = SET(no).StrainTagging.SR.radup(ind);%SET(no).StrainTagging.upsloperad(1,1); + outdata{line-1,col+1} = 'Upslope time'; + outdata{line,col+1} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.radupind(ind));%StrainTagging.upsloperad(1,2); + outdata{line-1,col+2} = 'Downslope'; + outdata{line,col+2} = SET(no).StrainTagging.SR.raddown(ind);%SET(no).StrainTagging.downsloperad(1,1); + outdata{line-1,col+3} = 'Downslope time'; + outdata{line,col+3} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.raddownind(ind));%SET(no).StrainTagging.downsloperad(1,2); + col = col+4; + outdata{line-2,col} = 'Longit. strain rate [%/s]'; + outdata{line-1,col} = 'Upslope'; + outdata{line,col} = SET(no).StrainTagging.SR.circup(ind);%SET(no).StrainTagging.upslopecircum(1,1); + outdata{line-1,col+1} = 'Upslope time'; + outdata{line,col+1} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.circupind(ind));%SET(no).StrainTagging.upslopecircum(1,2); + outdata{line-1,col+2} = 'Downslope'; + outdata{line,col+2} = SET(no).StrainTagging.SR.circdown(ind);%SET(no).StrainTagging.downslopecircum(1,1); + outdata{line-1,col+3} = 'Downslope time'; + outdata{line,col+3} = SET(no).TimeVector(1+SET(no).StrainTagging.SR.circdownind(ind));%SET(no).StrainTagging.downslopecircum(1,2); + col = col+4; + end end + line=line+3; end %line = line+1; %end end - end; %loop over image stack + end %loop over image stack if doStrain %store file @@ -2862,9 +2778,9 @@ function exportmultiplestrain_Callback(type) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -2873,7 +2789,7 @@ function exportmultiplestrain_Callback(type) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end currentsilent = DATA.Silent; % %Create output matrix @@ -3003,9 +2919,9 @@ function exportmultiplestrain_Callback(type) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -3014,7 +2930,7 @@ function exportmultiplestrain_Callback(type) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end currentsilent = DATA.Silent; % %Create output matrix @@ -3146,9 +3062,9 @@ function exportmultiplestrainRV_Callback(type) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -3157,7 +3073,7 @@ function exportmultiplestrainRV_Callback(type) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end % do strain? output=questdlg('Do you wish to redo strain analysis?'); @@ -3243,7 +3159,7 @@ function exportmultiplestrainRV_Callback(type) %#ok disp('Unknown image view plane'); end - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -3271,7 +3187,7 @@ function exportmultiplestrainRV_Callback(type) %#ok if ~isfield(SET(no),'StrainTagging')|| isempty(SET(no).StrainTagging) || ~isfield(SET(no).StrainTagging,'globalrad') %|| ismember(no,checked) %Skip no else - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -3285,7 +3201,7 @@ function exportmultiplestrainRV_Callback(type) %#ok %--- output --- %patient info outdata{line,1} = 'Patient name'; - outdata{line,2} = 'Patient ID'; + outdata{line,2} = 'Patient ID'; %'Filename'; outdata{line,3} = 'Heart Rate'; outdata{line,4} = 'Image Type'; outdata{line,5} = 'Global Peak Time Frame [s]'; @@ -3293,7 +3209,7 @@ function exportmultiplestrainRV_Callback(type) %#ok outdata{line,6}='Peak mean circ./longit. strain [%] (entire RV)'; line = line+1; - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -3302,10 +3218,12 @@ function exportmultiplestrainRV_Callback(type) %#ok %if isequal(type,imagetype) outdata{line,1} = SET(no).PatientInfo.Name; - outdata{line,2} = SET(no).PatientInfo.ID; + outdata{line,2} = SET(no).PatientInfo.ID; %files2load(fileloop).name; outdata{line,3} = SET(no).HeartRate; outdata{line,4} = sprintf('%s %s',SET(no).ImageType,SET(no).ImageViewPlane); outdata{line,5} = SET(no).TimeVector(SET(no).StrainTagging.peaktf); + + numseg=size(SET(no).StrainTagging.segmentalRVstrain,2); switch SET(no).ImageViewPlane case 'Short-axis' outdata{line,6} = mynanmean(SET(no).StrainTagging.globalRVstrain(1,SET(no).StrainTagging.peaktf,:)); @@ -3324,9 +3242,13 @@ function exportmultiplestrainRV_Callback(type) %#ok col=7; nbrslices=1; segstr={'Basal Lateral','Mid Lateral','Apical Lateral','Apical Septum','Mid Septum','Basal Septum'}; + otherwise + outdata{line,6} = mynanmean(SET(no).StrainTagging.globalRVstrain(1,SET(no).StrainTagging.peaktf,:)); + col=7; + nbrslices=1; + segstr={'Seg1: Basal Lateral','Seg2: Mid Lateral','Seg3: Apical Lateral','Seg4: Apical Septum','Seg5: Mid Septum','Seg6: Basal Septum'}; end - numseg=size(SET(no).StrainTagging.segmentalRVstrain,2); outdata{line-2,col}='RV Segmental Peak Strain Values For Each Segment '; for i=1:numseg @@ -3366,10 +3288,16 @@ function exportmultiplestrainRV_Callback(type) %#ok % end %Strain rate - if ~strcmp(SET(no).ImageViewPlane, 'Short-axis') - straincurve = SET(no).StrainTagging.globalRVstrain; + if strcmp(SET(no).ImageViewPlane, '2CH') || strcmp(SET(no).ImageViewPlane, '3CH') || strcmp(SET(no).ImageViewPlane, '4CH') + straincurve = squeeze(SET(no).StrainTagging.globalRVstrain); + elseif strcmp(SET(no).ImageViewPlane, 'Short-axis') + straincurve = squeeze(mynanmean(SET(no).StrainTagging.globalRVstrain(1,:,:),3)); else - straincurve = mynanmean(SET(no).StrainTagging.globalRVstrain(1,:,:),3); + if length(size(SET(no).StrainTagging.globalRVstrain)) == 2 + straincurve = squeeze(SET(no).StrainTagging.globalRVstrain); + else + straincurve = squeeze(mynanmean(SET(no).StrainTagging.globalRVstrain(1,:,:),3)); + end end strainratecurve=conv2([1 0 -1],1,straincurve','valid')/(2*SET(no).TIncr); @@ -3447,7 +3375,7 @@ function exportmultiplestrainRV_Callback(type) %#ok line=line+3; end - end; %loop over image stack + end %loop over image stack @@ -3518,9 +3446,9 @@ function exportmultiplestrainRVgraphs_Callback(type) %#ok pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,sprintf('Select a folder with .%s files',suffix)); if isequal(pathname,0) - myfailed('Aborted.',DATA.GUI.Segment); +% myfailed('Aborted.',DATA.GUI.Segment); return; -end; +end %Find files to process files2load = dir([pathname filesep sprintf('*.%s',suffix)]); @@ -3529,7 +3457,7 @@ function exportmultiplestrainRVgraphs_Callback(type) %#ok if numfiles==0 myfailed('Found no files to summarize.',DATA.GUI.Segment); return; -end; +end % do strain? output=questdlg('Do you wish to redo strain analysis?'); @@ -3594,7 +3522,7 @@ function exportmultiplestrainRVgraphs_Callback(type) %#ok disp('Unknown image view plane'); end - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -3622,7 +3550,7 @@ function exportmultiplestrainRVgraphs_Callback(type) %#ok if ~isfield(SET(no),'StrainTagging')|| isempty(SET(no).StrainTagging) || ~isfield(SET(no).StrainTagging,'globalrad') %|| ismember(no,checked) %Skip no else - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -3641,7 +3569,7 @@ function exportmultiplestrainRVgraphs_Callback(type) %#ok outdata{line,4} = 'Image Type'; line = line+1; - switch SET(no).ImageType; + switch SET(no).ImageType case {'Cine', 'Feature tracking'} imagetype='cine'; case 'Strain from tagging' @@ -3683,7 +3611,7 @@ function exportmultiplestrainRVgraphs_Callback(type) %#ok end line=line+3; end - end; %loop over image stack + end %loop over image stack if doStrain @@ -3759,36 +3687,36 @@ function exportthisstack(doheader) %#ok scarno = []; else scarno = no; - end; + end if isempty(SET(no).Flow) flowno = []; else flowno = no; - end; + end if isempty(SET(no).MaR) marno = []; else marno = no; - end; -end; + end +end if isnan(no) no = NO; -end; +end if isempty(no) no = NO; -end; +end if nargin<2 includenormalized = yesno('Do you want to include BSA normalized values?'); -end; +end -outdata = cell(1,20); +outdata = cell(1,67); if nargin==0 doheader = true; -end; +end if doheader %Write Header @@ -3796,18 +3724,18 @@ function exportthisstack(doheader) %#ok row = 2; else row = 1; -end; +end if nargout>0 varargout = cell(1,nargout); -end; +end %Write data if ~onlyone outdata{row, 1} = SET(no).FileName; else outdata{row, 1} = sprintf('%d-%s %s',no,SET(no).ImageType,SET(no).ImageViewPlane); -end; +end outdata{row, 2} = SET(no).PatientInfo.Name; outdata{row, 3} = SET(no).PatientInfo.ID; @@ -3827,13 +3755,13 @@ function exportthisstack(doheader) %#ok rvm = 0.5*(SET(no).RVM(SET(no).EDT)+SET(no).RVM(SET(no).EST)); catch %#ok rvm = NaN; -end; +end if numel(SET(no).PatientInfo.BSA) ~= 1 || SET(no).PatientInfo.BSA==0 bsa_1 = NaN; else bsa_1 = 1/SET(no).PatientInfo.BSA; -end; +end outdata{row,12} = lvm; outdata{row,13} = lvm*1.05; @@ -3848,13 +3776,13 @@ function exportthisstack(doheader) %#ok else outdata{row,19} = SET(no).SV; outdata{row,20} = bsa_1*SET(no).SV; -end; +end if isequal(SET(no).EF,0) && (SET(no).EDV>0) outdata{row,21} = 100*(SET(no).EDV-SET(no).ESV)/SET(no).EDV; else outdata{row,21} = 100*SET(no).EF; -end; +end outdata{row,22}= SET(no).HeartRate*SET(no).SV/1000; outdata{row,23}= bsa_1*SET(no).HeartRate*SET(no).SV/1000; @@ -3920,10 +3848,10 @@ function exportthisstack(doheader) %#ok %For backwards compability. if isnan(SET(scarno).Scar.MOPercentage) viability('viabilitycalcvolume',scarno); - end; + end outdata{row,46} = SET(scarno).Scar.MOPercentage; - end; + end else outdata{row,36} = NaN; outdata{row,37} = NaN; @@ -3936,7 +3864,7 @@ function exportthisstack(doheader) %#ok outdata{row,44} = NaN; outdata{row,45} = NaN; outdata{row,46} = NaN; -end; +end if ~isempty(marno) && ~isempty(SET(marno).MaR) lvmmaredt = SET(marno).LVM(SET(marno).EDT); @@ -3964,17 +3892,18 @@ function exportthisstack(doheader) %#ok outdata{row,53} = NaN; outdata{row,54} = NaN; end - end; + end else outdata{row,47} = NaN; outdata{row,48} = NaN; outdata{row,49} = NaN; outdata{row,50} = NaN; -end; +end %Flow if ~isempty(flowno) rowoffset = 0; + %Loop over each flow stack for loop=1:length(flowno) NO = flowno(loop); @@ -3987,27 +3916,33 @@ function exportthisstack(doheader) %#ok hr = flowgui.hr; co = flowgui.nettotvol.*flowgui.hr;%SBT20160620 - for rloop=1:length(tots) - outdata{row+rowoffset,55} = SET(NO).Roi(rloop).Name; + roiname = SET(NO).Roi(rloop).Name; + outdata{row+rowoffset,55} = roiname; outdata{row+rowoffset,56} = tots(rloop); outdata{row+rowoffset,57} = co(rloop); %SBT20160620 outdata{row+rowoffset,58} = hr;%SBT20160620 + + if isequal(roiname,'Coronary sinus stress') + outdata{row,65} = co(rloop)/outdata{row,13}; %flow/lvm + elseif isequal(roiname,'Coronary sinus rest') + outdata{row,66} = co(rloop)/outdata{row,13}; %flow/lvm + end + rowoffset = rowoffset+1; - end; + end reportflow('close_Callback');%SBT20160620 end - end; - - end; -end; + end + end +end %Measurements if ~onlyone loopover = 1:length(SET); else loopover = no; -end; +end msdone = 0; for sloop=loopover @@ -4015,20 +3950,26 @@ function exportthisstack(doheader) %#ok outdata{row+msdone,59} = SET(sloop).Measure(mloop).Name; outdata{row+msdone,60} = SET(sloop).Measure(mloop).Length; msdone = msdone + 1; - end; -end; + end +end outdata{row,61} = SET(no).RVPFR; outdata{row,62} = SET(no).RVPER; outdata{row,63} = lvmed; outdata{row,64} = lvmes; +if ~isempty(outdata{row,65}) && ~isempty(outdata{row,66}) + outdata{row,67} = abs(outdata{row,65})/abs(outdata{row,66}); %qCS-stress/qCS-rest +else + outdata{row,67} = NaN; +end + %If not wanted remove non normalized values. ind = true(1,size(outdata,2)); if ~includenormalized [~,indforbsa] = header(onlyone); ind(indforbsa) = false; -end; +end outdata = outdata(:,ind); %If called with no output arguments then copy to clipboard. @@ -4036,8 +3977,8 @@ function exportthisstack(doheader) %#ok segment('cell2clipboard',outdata); else varargout{1} = outdata; -end; - +end + %------------------------------ function [x,y] = meshfixer(x,y) %------------------------------ @@ -4065,12 +4006,12 @@ function exportthisstack(doheader) %#ok mindist = dist; xmin = xtest; ymin = ytest; - end; + end %rotate for next iteration xtest = [xtest(2:end) xtest(1)]; ytest = [ytest(2:end) ytest(1)]; - end; + end %Store the best match x(loop,:) = xmin; @@ -4079,7 +4020,7 @@ function exportthisstack(doheader) %#ok %Take the new row xrow = x(loop,:); yrow = y(loop,:); -end; +end %--------------------------------------------------------------------------------- function export2stl_helper(no,x,y,resolution,tf,closeapex,fignr,pathname,filename) @@ -4105,7 +4046,7 @@ function export2stl_helper(no,x,y,resolution,tf,closeapex,fignr,pathname,filenam if ~isequal(sum(logind),last-first+1) myfailed('None consecutive segmentation detected (slices)'); return; -end; +end x = x(first:last,:); y = y(first:last,:); z = z(first:last,:); @@ -4135,7 +4076,7 @@ function export2stl_helper(no,x,y,resolution,tf,closeapex,fignr,pathname,filenam mesh2stl(rl,ap,fh,resolution,closeapex,fignr,fid); %Called with fid rather than pathname and filename else mesh2stl(rl,ap,fh,resolution,closeapex,fignr,pathname,filename); -end; +end %--------------------------- function export2stl_Callback %#ok @@ -4167,14 +4108,14 @@ function export2stl_helper(no,x,y,resolution,tf,closeapex,fignr,pathname,filenam x = SET(no).RVEpiX; y = SET(no).RVEpiY; otherwise - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end if isempty(x) || isempty(y) myfailed(dprintf('No data in %s',l{c})); return; -end; +end %--- Calculate suggested resolution resolution = (SET(no).ResolutionX+SET(no).ResolutionY+SET(no).SliceThickness+SET(no).SliceGap)/3; @@ -4183,15 +4124,15 @@ function export2stl_helper(no,x,y,resolution,tf,closeapex,fignr,pathname,filenam [s,ok] = inputstruct(s,'Set resolution of STL file [mm]'); if ~ok mywarning('Invalid input, using default.'); -end; +end resolution = s.Resolution_mm; closeapex = s.CloseApex; -[filename,pathname,~,ok] = myuiputfile('*.stl','Select filename for STL file export'); +[filename,pathname,~,ok] = myuiputfile('*.stl',dprintf('Select filename for STL file export')); if ~ok myfailed('Aborted or illegal file selected.'); return; -end; +end figure(99); clf; @@ -4214,7 +4155,7 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, if nargin<11 error('Expected 11 input arguments.'); -end; +end if isempty(fignr) doplot = false; @@ -4222,7 +4163,7 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, doplot = true; figure(fignr); hold on; -end; +end %Extract basal rows from surface 1 basex1 = x1; @@ -4271,7 +4212,7 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, y2 = apexy2; slice2 = apexslice2; closeit = closeapex; - end; + end if closeit %Convert to 3D coordinates for surface 1 @@ -4313,7 +4254,7 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, fh2 = ofh1; d2 = od1; - end; + end %Resample newn1 = round(d1/resolution); @@ -4322,16 +4263,16 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, n2 = 1:length(rl2); if newn1<1 newn1 = 1; - end; + end if newn2<1 newn2 = 1; - end; + end if newn1>length(rl1) newn1 = length(rl1); - end; + end if newn2>length(rl2) newn2 = length(rl2); - end; + end ni1 = linspace(1,length(rl1)-(length(rl1)-1)/newn1,newn1); ni2 = linspace(1,length(rl2)-(length(rl2)-1)/newn2,newn2); rl1 = interp1(n1,rl1,ni1); @@ -4365,14 +4306,14 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, ap2best = aptest; fh2best = fhtest; mindist = dist; - end; + end %Shift it rltest = [rltest(2:end) rltest(1)]; aptest = [aptest(2:end) aptest(1)]; fhtest = [fhtest(2:end) fhtest(1)]; - end; + end %Loop over r1 to create triangles (r1 got more or equal points as r2) nextind = [1:length(rl1) 1]; @@ -4407,16 +4348,16 @@ function exportclosesurfaces(no1,x1,y1,no2,x2,y2,closebase,closeapex,resolution, if doplot %Graphical update patch([x1;x2;x3],[y1;y2;y3],[z1;z2;z3],zeros(3,1)); - end; + end - end; + end - end; %Closeit -end; %Loop over base,apex (1:2) + end %Closeit +end %Loop over base,apex (1:2) if doplot hold off; -end; +end %----------------------------------------------- function exportlv2stl(no,tf,fignr,filename,resolution) @@ -4432,7 +4373,7 @@ function exportlv2stl(no,tf,fignr,filename,resolution) if isequal(fid,-1) myfailed(dprintf('Could not open the file %s for writing.',[pathname filename])); return; -end; +end %Extract endocardium endox = SET(no).EndoX; @@ -4488,7 +4429,7 @@ function exportlv2stl(no,tf,fignr,filename,resolution) if isempty(SET(no).EndoX) || isempty(SET(no).EpiX) myfailed('Either endocardium or epicardium is missing.'); return; -end; +end %Fix resolution resolution = 5; %Later ask @@ -4497,9 +4438,9 @@ function exportlv2stl(no,tf,fignr,filename,resolution) pathname = DATA.Pref.exportpath; %Later asks pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end filename = 'lv_export.stl'; %Call the function to do it. @@ -4552,11 +4493,11 @@ function exportlv2stl(no,tf,fignr,filename,resolution) %hold off; %pause - end; + end - end; + end -end; +end %----------------------------------------------------- function exportrv2stl(no,tf,fignr,filename,resolution) @@ -4573,7 +4514,7 @@ function exportrv2stl(no,tf,fignr,filename,resolution) if isequal(fid,-1) myfailed(dprintf('Could not open the file %s for writing.',[pathname filename])); return; -end; +end %Extract endocardium endox = SET(no).RVEndoX; @@ -4634,7 +4575,7 @@ function exportrv2stl(no,tf,fignr,filename,resolution) if isempty(SET(no).RVEndoX) myfailed('RV endocardium is missing.'); return; -end; +end %Fix resolution resolution = 5; %Later ask @@ -4643,9 +4584,9 @@ function exportrv2stl(no,tf,fignr,filename,resolution) pathname = DATA.Pref.exportpath; pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end filename = 'rv_export.stl'; %Call the function to do it. @@ -4669,19 +4610,19 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) disp('Exporting LV'); if (~isempty(SET(no).EndoX)) && (~isempty(SET(no).EpiX)) exportlv2stl(no,tf,fignr,[pathname filesep filetemplate '-lv.stl'],resolution) -end; +end %Export RV disp('Exporting RV'); if (~isempty(SET(no).RVEndoX)) exportrv2stl(no,tf,fignr,[pathname filesep filetemplate '-rv.stl'],resolution) -end; +end %Export LV atria disp('Exporting left atria (RV Epi)'); if (~isempty(SET(no).RVEpiX)) exportleftatria2stl(no,tf,fignr,[pathname filesep filetemplate '-leftatria.stl'],resolution); -end; +end %**** Export ROI's **** @@ -4689,7 +4630,7 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) names = cell(1,SET(no).RoiN); for loop = 1:length(names) names{loop} = SET(no).Roi(loop).Name; -end; +end names = union(names,{}); %--- Loop over roi uniquenames and export @@ -4701,15 +4642,15 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) %Loop over ROI's for loop = 1:SET(no).RoiN - if isequal(SET(no).Roi(loop).Name,templatename); + if isequal(SET(no).Roi(loop).Name,templatename) if isnan(x(1,1,SET(no).Roi(loop).Z)) x(:,:,SET(no).Roi(loop).Z) = SET(no).Roi(loop).X; y(:,:,SET(no).Roi(loop).Z) = SET(no).Roi(loop).Y; else mywarning('Two ROIs in the same slice. Ambigous result.',DATA.GUI.Segment); - end; - end; - end; + end + end + end %Loop over ED and ES for tloop = 1:2 @@ -4719,7 +4660,7 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) roifilename = sprintf('%s_%s_%s.stl',filetemplate,'ED',templatename); else roifilename = sprintf('%s_%s_%s.stl',filetemplate,'ES',templatename); - end; + end %Open file @@ -4727,7 +4668,7 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) if isequal(fid,-1) myfailed(dprintf('Could not open the file %s for writing.',[pathname filesep roifilename])); return; - end; + end %Start the file fprintf(fid,'solid segment stl \n'); @@ -4737,12 +4678,12 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) tf = SET(no).EDT; else tf = SET(no).EST; - end; + end endox = x(:,tf,:); endoy = y(:,tf,:); - disp(dprintf('Exporting ROI %s',templatename)); %#ok + disp(sprintf('Exporting ROI %s',templatename)); closeapex = false; %flip it to get other direction (normal inwards) @@ -4773,8 +4714,8 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) %Close the file fprintf(fid,'endsolid stl\n'); fclose(fid); - end; %tloop, i.e ED and ES -end; %names (roi's) + end %tloop, i.e ED and ES +end %names (roi's) %------------------------------ function exportall2stl_Callback %#ok @@ -4800,7 +4741,7 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) [s,ok] = inputstruct(s,'Set resolution and name of STL file'); if ~ok mywarning('Invalid input, using default.'); -end; +end resolution = s.Resolution_mm; filetemplate = s.File_Name; @@ -4808,9 +4749,9 @@ function exportall2stl(no,pathname,filetemplate,fignr,resolution,tf) pathname = DATA.Pref.exportpath; pathname = myuigetdir(pathname,'Select a folder where to the output files.'); if isequal(pathname,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end tf = SET(no).CurrentTimeFrame; @@ -4842,7 +4783,7 @@ function exportleftatria2stl(no,tf,fignr,filename,resolution) if isequal(fid,-1) myfailed(dprintf('Could not open the file %s for writing.',[pathname filename])); return; -end; +end %Extract endocardium endox = SET(no).RVEpiX; @@ -4899,9 +4840,9 @@ function exportleftatria2stl(no,tf,fignr,filename,resolution) pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end files2load = dir([pathname filesep '*.mat']); numfiles = length(files2load); @@ -4909,14 +4850,14 @@ function exportleftatria2stl(no,tf,fignr,filename,resolution) if numfiles == 0 myfailed('No files for STL export.'); return; -end; +end %Ask for resolution s.Resolution_mm = 3; [s,ok] = inputstruct(s,'Set resolution and name of STL file'); if ~ok mywarning('Invalid input, using default.'); -end; +end resolution = s.Resolution_mm; fignr = []; %no plotting. @@ -4927,7 +4868,7 @@ function exportleftatria2stl(no,tf,fignr,filename,resolution) %--- Load file DATA.Silent = true; - disp(dprintf('Loading %s.',files2load(fileloop).name)); %#ok + disp(dprintf('Loading %s.',files2load(fileloop).name)); SET = []; %#ok load([pathname filesep files2load(fileloop).name],'-mat'); SET = setstruct; @@ -4954,7 +4895,7 @@ function exportleftatria2stl(no,tf,fignr,filename,resolution) h = mywaitbarupdate(h); -end; +end mywaitbarclose(h); DATA.Silent = false; \ No newline at end of file diff --git a/source/externalpacs.p b/source/externalpacs.p index 8bf1c23..167b3ad 100644 Binary files a/source/externalpacs.p and b/source/externalpacs.p differ diff --git a/source/extractscanner.p b/source/extractscanner.p index 1f22e97..d0d0802 100644 Binary files a/source/extractscanner.p and b/source/extractscanner.p differ diff --git a/source/extractvenc.p b/source/extractvenc.p index b40f929..5372944 100644 Binary files a/source/extractvenc.p and b/source/extractvenc.p differ diff --git a/source/fastdicominfo.p b/source/fastdicominfo.p index f348767..52bcb69 100644 Binary files a/source/fastdicominfo.p and b/source/fastdicominfo.p differ diff --git a/source/fastimprofile.mexw32 b/source/fastimprofile.mexw32 deleted file mode 100644 index 9171d72..0000000 Binary files a/source/fastimprofile.mexw32 and /dev/null differ diff --git a/source/fastlabelunknown.mexa64 b/source/fastlabelunknown.mexa64 deleted file mode 100644 index ea1a47e..0000000 Binary files a/source/fastlabelunknown.mexa64 and /dev/null differ diff --git a/source/fastlabelunknown.mexmaci64 b/source/fastlabelunknown.mexmaci64 deleted file mode 100644 index 5b035c8..0000000 Binary files a/source/fastlabelunknown.mexmaci64 and /dev/null differ diff --git a/source/fastlabelunknown.mexw32 b/source/fastlabelunknown.mexw32 deleted file mode 100644 index b788632..0000000 Binary files a/source/fastlabelunknown.mexw32 and /dev/null differ diff --git a/source/fastlabelunknown.mexw64 b/source/fastlabelunknown.mexw64 deleted file mode 100644 index 3cbe46c..0000000 Binary files a/source/fastlabelunknown.mexw64 and /dev/null differ diff --git a/source/fastlevelset.mexw32 b/source/fastlevelset.mexw32 deleted file mode 100644 index eab2399..0000000 Binary files a/source/fastlevelset.mexw32 and /dev/null differ diff --git a/source/fastmarch.mexw32 b/source/fastmarch.mexw32 deleted file mode 100644 index 45d07f4..0000000 Binary files a/source/fastmarch.mexw32 and /dev/null differ diff --git a/source/fastpoly2mask.mexw32 b/source/fastpoly2mask.mexw32 deleted file mode 100644 index e0077cc..0000000 Binary files a/source/fastpoly2mask.mexw32 and /dev/null differ diff --git a/source/fastremap.mexw32 b/source/fastremap.mexw32 deleted file mode 100644 index bf32589..0000000 Binary files a/source/fastremap.mexw32 and /dev/null differ diff --git a/source/filemenu.m b/source/filemenu.m index 2e4258d..c6d2502 100644 --- a/source/filemenu.m +++ b/source/filemenu.m @@ -21,12 +21,12 @@ if ~DATA.DataLoaded loadednext = 0; return; -end; +end if length(SET)<1 loadednext = 0; return; -end; +end %Get filename from first image stack. filename = SET(1).FileName; @@ -37,16 +37,16 @@ pos = []; for loop=1:length(f) - if isequal(f(loop).name,[filename '.mat']); + if isequal(f(loop).name,[filename '.mat']) pos = loop; - end; -end; + end +end if isempty(pos) myfailed('Could not find the current file, removed?'); loadednext = 0; return; -end; +end if (pos+1)<=length(f) @@ -57,7 +57,7 @@ myfailed('Loading next aborted.'); loadednext = 0; return; - end; + end try %Load @@ -75,17 +75,22 @@ openfile('setupstacksfrommat',NO); segment('renderstacksfrommat'); + + %Does all graphical updates + if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; + end DATA.NeedToSave = false; catch me mydispexception(me); - end; + end loadednext = 1; else myfailed('Last file'); loadednext = 0; -end; +end %-------------------------------------- function savetopatientdatabase_Callback @@ -93,9 +98,7 @@ %Callback to save image stacks to patientdatabase. Uses functions in %patientdatabase. global DATA SET NO - -set(DATA.Handles.databaseaddicon,'state','off'); - +tools('closeallongoinginterpolations'); [pathname,filename,ext] = fileparts(SET(NO).FileName); if DATA.Pref.AskAddComment @@ -111,7 +114,7 @@ patientdatabase('savetodatabase',pathname,filename,ext,[]); catch me mydispexception(me); - end; + end end %------------------------ @@ -120,7 +123,7 @@ %Saves all image stacks to one .mat file. Calls GUI method %filesaveallas_Callback which is the workhorse when saving image stacks. global DATA SET - +tools('closeallongoinginterpolations'); filenames = unique({SET.FileName}); if numel(filenames) > 1 i = mymenu('Multiple file names were found in data. Select where to save', ... @@ -142,14 +145,14 @@ else %Call Save as instead DATA.filesaveallas_Callback; -end; +end DATA.LastSaved = now; flushlog; -%-------------------------------------------------------------------- -function fail = saveallas_helper(pathname,filename,topatientdatabase) -%-------------------------------------------------------------------- +%--------------------------------------------------------------------------- +function fail = saveallas_helper(pathname,filename,topatientdatabase,silent) +%--------------------------------------------------------------------------- %Save all image stacks to the file specified. It also stores current view %and modes etc. @@ -158,11 +161,13 @@ if nargin<3 topatientdatabase = false; %Default save to disk not patientdatabase %Setting this to true only changes the final saved display message. -end; +end -fail=0; +if nargin<4 + silent = DATA.Silent; +end -set(DATA.Handles.filesaveicon,'state','off'); +fail=0; % if not(DATA.DataLoaded) % myfailed('Nothing to save.',DATA.GUI.Segment); @@ -171,45 +176,55 @@ %--- Get filename and pathname if nargin==0 - temp = pwd; + temp = DATA.SegmentFolder; if exist(DATA.Pref.exportpath,'dir') cd(DATA.Pref.exportpath); else mydisp('Warning: Export path does not exist, please check preferences.'); - end; + end filename = DATA.generatesavefilename; - [filename,pathname] = myuiputfile(filename,'Save all image stacks to one file'); + [filename,pathname] = myuiputfile(filename,dprintf('Save all image stacks to one file')); cd(temp); else %Take from input two argument if nargin<2 myfailed('Expected two input arguments.',DATA.GUI.Segment); return; - end; -end; + end +end if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); - fail=1; +% myfailed('Operation cancelled.',DATA.GUI.Segment); + fail = 1; return; -end; +end if length(filename)>4 if ~isequal(filename(end-3:end),'.mat') filename = [filename '.mat']; - end; + end else filename = [filename '.mat']; -end; +end myworkon; +%Store info about current user (e.g. username, computer name, date) +%according to user preferences +if DATA.Pref.SaveUserInfo + SET(NO).LastUserInfo.Username = getenv('username'); + SET(NO).LastUserInfo.ComputerName = getenv('computername'); + SET(NO).LastUserInfo.ModificationDate = datestr(now,'yyyy-mm-dd HH:MM'); +else + SET(NO).LastUserInfo = ''; +end + %Store filename for loop=1:length(SET) SET(loop).FileName = [pathname filesep filename]; -end; +end %Store current view SET(1).View = []; @@ -221,7 +236,11 @@ SET(1).View.CurrentPanel = DATA.CurrentPanel; SET(1).View.CurrentTheme = DATA.CurrentTheme; SET(1).View.CurrentTool = DATA.CurrentTool; -preview = DATA.DATASETPREVIEW; %#ok %saved to file +SET(1).View.LVNO = DATA.LVNO; +SET(1).View.RVNO = DATA.RVNO; +SET(1).View.FlowNO = DATA.FlowNO; +SET(1).View.FlowROI = DATA.FlowROI; +preview = DATA.DATASETPREVIEW; %saved to file info = SET(NO).PatientInfo; %fake data @@ -250,80 +269,95 @@ info.IntensityOffset = 0; info.MultiDataSet = true; info.Modality = SET(1).Modality; -im = []; %#ok %saved to file -setstruct = SET; %#ok %saved to file + +im = []; %saved to file +setstruct = SET; %saved to file lastwarn(''); -warnchk = 'cannot be saved'; +warnchk = 'not saved'; try save(fullfile(pathname,filename),'preview','info','im','setstruct', DATA.Pref.SaveVersion); warnmsg = lastwarn; lastwarn(''); - if ~isempty(strfind(warnmsg,warnchk)) + if contains(warnmsg,warnchk) + mydisp('Retrying using -v7.3 version.'); save(fullfile(pathname,filename),'preview','info','im','setstruct','-v7.3') warnmsg = lastwarn; lastwarn(''); - if ~isempty(strfind(warnmsg,warnchk)) - error('Dataset cannot be saved'); + if ~isempty(warnmsg) + myfailed('Dataset cannot be saved'); + fail = 1; + myworkoff; + return; end end myworkoff; catch %#ok - if ~DATA.Silent + if ~silent myfailed('Could not save data. Write permission? Disk full?',DATA.GUI.Segment); end fail = 1; myworkoff; return; -end; +end -if not(DATA.Silent) +if not(silent) if topatientdatabase mymsgbox('Image Stacks Saved to Patient Database.'); else + filename = SET(NO).FileName; if length(SET)>1 - stri = dprintf('All image stacks and segmentation stored to %s.',... - SET(NO).FileName); + stri = dprintf('All image stacks and segmentation stored to %s.',filename); else - stri = dprintf('Image stack and segmentation stored to %s.',... - SET(NO).FileName); - end; + stri = dprintf('Image stack and segmentation stored to %s.',filename); + end mymsgbox(stri,'Save successful.',DATA.GUI.Segment); - end; -end; + end +end if ~isempty(SET(1).FileName) str = sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),sprintf('Saved file %s',SET(1).FileName),SET(1).PatientInfo.ID); else str = sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),sprintf('Saved file %s',SET(1).PathName),SET(1).PatientInfo.ID); end - DATA.adduserevent(str); + +DATA.adduserevent(str); %DATA.adduserevent([' Saved file: ', SET(1).FileName]) %DATA.adduserevent(['Time:' datestr(now,'yyyymmddHHMMSS')]) %DATA.adduserevent([' Patient name: ', SET(1).PatientInfo.Name]) %DATA.adduserevent([' Patient ID: ', SET(1).PatientInfo.ID]) DATA.LastSaved = now; DATA.NeedToSave = false; -set(DATA.Handles.filesaveicon,'enable','off'); +% set(DATA.Handles.filesaveicon,'enable','off'); DATA.updatetitle; flushlog; +%--------------------------- +function savetoopenapps_Callback +%--------------------------- +%Send image stacks to the folder provide by command line parameter +% save into the siemens catalogue + try + applysiemensoptions('savetosiemens_Callback') + catch e + myfailed(e.message); + end + %--------------------------- function savetopacs_Callback %--------------------------- %Send image stacks to PACS. This function should display a list of %available PACS (.con files) and when user has selected store files on disk %temporarily and then send the files to the PACS. -global DATA - -set(DATA.Handles.pacsaddicon,'state','off'); +% save to pacs try - pacs('savetopacs'); + pacsaccess('savetopacs'); mymsgbox('Image stacks saved to PACS.') catch e myfailed(e.message); end + %---------------------------- function savecurrent_Callback %---------------------------- @@ -334,25 +368,25 @@ if not(DATA.DataLoaded) myfailed('No data to save.',DATA.GUI.Segment); return; -end; +end -temp = pwd; +temp = DATA.SegmentFolder; if exist(DATA.Pref.exportpath,'dir') cd(DATA.Pref.exportpath); else mydisp('Warning: Export path does not exist, please check preferences.'); -end; +end -[filename,pathname] = myuiputfile('*.mat','Save current image stack'); +[filename,pathname] = myuiputfile('*.mat',dprintf('Save current image stack')); cd(temp); if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); +% myfailed('Operation cancelled.',DATA.GUI.Segment); return; -end; +end %IM and preview are saved to disk -preview = SET(NO).IM(:,:,round(SET(NO).TSize/2),round(SET(NO).ZSize/2)); %#ok +preview = SET(NO).IM(:,:,round(SET(NO).TSize/2),round(SET(NO).ZSize/2)); info = SET(NO).PatientInfo; info.NFrames = SET(NO).TSize; info.NumSlices = SET(NO).ZSize; @@ -378,7 +412,7 @@ info.IntensityScaling = SET(NO).IntensityScaling; info.IntensityOffset = SET(NO).IntensityOffset; info.Modality = SET(NO).Modality; -im = calcfunctions('calctruedata',SET(NO).IM,NO); %#ok +im = calcfunctions('calctruedata',SET(NO).IM,NO); setstruct = SET(SET(NO).Linked); linkies = setstruct(1).Linked; newlinkies = 1:length(linkies); @@ -411,7 +445,7 @@ myfailed('Could not save data. Write permission? Disk full?',DATA.GUI.Segment); myworkoff; return; -end; +end mymsgbox('Current image stack stored.','',DATA.GUI.Segment); DATA.LastSaved = now; @@ -430,22 +464,22 @@ function savesegmentation_Callback(pathname,filename) if nargin==0 pathname = DATA.Preview.PathName; %pathname = DATA.Pref.exportpath; - [filename,pathname] = myuiputfile([pathname filesep '*.seg'],'Save segmentation as'); + [filename,pathname] = myuiputfile([pathname filesep '*.seg'],dprintf('Save segmentation as')); if isequal(filename,0)||isequal(pathname,0) mydisp('Save segmentation aborted by user'); return; - end; + end else if nargin<2 myfailed('Too few input arguments.',DATA.GUI.Segment); return; - end; -end; + end +end [temppath,tempname,ext] = fileparts(fullfile(pathname,filename)); if isempty(ext) filename = [filename '.seg']; -end; +end SEG.ProgramVersion = DATA.ProgramVersion; SEG.EndoX = SET(NO).EndoX; @@ -520,7 +554,7 @@ function savesegmentation_Callback(pathname,filename) SEG.OrgTSize = SET(NO).OrgTSize; if not(isempty(SET(NO).Scar)) SEG.Scar = SET(NO).Scar; -end; +end try myworkon; save(fullfile(pathname,filename),'SEG', DATA.Pref.SaveVersion); @@ -529,12 +563,12 @@ function savesegmentation_Callback(pathname,filename) myfailed('Could not save data. Write permission? Disk full?',DATA.GUI.Segment); myworkoff; return; -end; +end DATA.LastSaved = now; %--------------------------------- -function success = savesegdicom_Callback(filename) %#ok +function success = savesegdicom_Callback(filename) %--------------------------------- %Save image stack as DICOM file global DATA SET NO @@ -543,30 +577,30 @@ function savesegmentation_Callback(pathname,filename) if not(DATA.DataLoaded) myfailed('Nothing to save.',DATA.GUI.Segment); return; -end; +end %--- Get filename and pathname if(nargin < 1) - temp = pwd; + temp = DATA.SegmentFolder; if exist(DATA.Pref.exportpath,'dir') - cd(DATA.Pref.exportpath); + cd(DATA.Pref.exportpath); else - mydisp('Warning: Export path does not exist, please check preferences.'); - end; + mydisp('Warning: Export path does not exist, please check preferences.'); + end filename = [SET(NO).PatientInfo.Name '.segdicom']; - [filename,pathname] = myuiputfile(filename,'Save all image stacks to one file'); + [filename,pathname] = myuiputfile(filename,dprintf('Save all image stacks to one file')); cd(temp); if isequal(filename,0) - myfailed('Operation cancelled.',DATA.GUI.Segment); +% myfailed('Operation cancelled.',DATA.GUI.Segment); return; - end; + end if length(filename)>=9 if ~isequal(filename(end-8:end),'.segdicom') filename = [filename '.segdicom']; - end; + end else filename = [filename '.segdicom']; - end; + end filename = fullfile(pathname, filename); end @@ -580,6 +614,10 @@ function savesegmentation_Callback(pathname,filename) SET(1).View.CurrentPanel = DATA.CurrentPanel; SET(1).View.CurrentTheme = DATA.CurrentTheme; SET(1).View.CurrentTool = DATA.CurrentTool; +SET(1).View.LVNO = DATA.LVNO; +SET(1).View.RVNO = DATA.RVNO; +SET(1).View.FlowNO = DATA.FlowNO; +SET(1).View.FlowROI = DATA.FlowROI; % Save the data study_uid = segment('getfieldifcommon',SET, 'StudyUID'); @@ -617,7 +655,7 @@ function savesegmentation_Callback(pathname,filename) success = true; %-------------------------------------------------------- -function closecurrentimagestack_Callback(frompreviewmenu) %#ok +function closecurrentimagestack_Callback(frompreviewmenu) %-------------------------------------------------------- %Close current image stack, i.e the current image stack is deleted. It %also takes care of eventual cross couplings between image stacks. @@ -625,7 +663,7 @@ function closecurrentimagestack_Callback(frompreviewmenu) %#ok flushlog; -if nargin>0 +if nargin>0 && frompreviewmenu %don't need to get clicked coordinates since when bringing up previemenu switchimagestack is called % checking clicked coordinates also results in errors since CurrentPoint % not alwasy is inside the previewaxes but rather in the previewmenu when @@ -637,22 +675,24 @@ function closecurrentimagestack_Callback(frompreviewmenu) %#ok % y=p(1,2); % vertical % no = floor(y/DATA.GUISettings.ThumbnailSize)+1; % DATA.switchtoimagestack(no); -end; + no = segment_main('getclickedpreview'); +else + no = NO; +end if ~DATA.Silent if (DATA.NeedToSave) - if ~yesno('Unsaved changes: are you sure you want to delete the current image stack?',[],DATA.GUI.Segment); + if ~yesno('Unsaved changes: are you sure you want to delete the current image stack?',[],DATA.GUI.Segment) return; - end; + end end -end; +end if length(SET) < 2 DATA.filecloseall_Callback(true); return; end -closeimagestack(NO); -DATA.switchtoimagestack(NO,true); %force +closeimagestack(no); flushlog; %---------------------------------------------- @@ -660,12 +700,13 @@ function closemultipleimagestacks_Callback(arg) %---------------------------------------------- %Close multiple user selected image stacks. %Useful when a lot of stacks are open. + global SET NO if nargin < 1 %Launch GUI - fig = openfig('closemultiple.fig'); - handles = guihandles(fig); + fig = mygui('closemultiple.fig'); + handles = fig.handles; stackc = cell(1,numel(SET)); for no = 1:numel(SET) stackc{no} = sprintf('%d. %s, %s',no,SET(no).ImageType,SET(no).ImageViewPlane); @@ -686,7 +727,7 @@ function closemultipleimagestacks_Callback(arg) for no = nos(end:-1:1) closeimagestack(no) end - segment('switchtoimagestack',NO,true); %NO set in subfcn, force + viewfunctions('setview',1,1,NO,{'one'})%segment('switchtoimagestack',NO,true); %NO set in subfcn, force end flushlog; close(handles.figure1); @@ -698,31 +739,17 @@ function closeimagestack(no) %--------------------------- %Close image stack no. Takes care of possible cross couplings %between image stacks -global DATA SET NO -resetLVNO=0; -resetRVNO=0; -resetFlowNO=0; - -if any(no<=DATA.LVNO) -resetLVNO=1; -end -if no<=DATA.RVNO -resetRVNO=1; -end - -if no<=DATA.FlowNO -resetFlowNO=1; -end +global DATA SET NO %Make sure report is preserved, if removing stack number 1 if no == 1 SET(2).Report = SET(1).Report; end -if ~isempty(SET(no).Flow) - SET(no).Flow=[]; -end +% if ~isempty(SET(no).Flow) +% SET(no).Flow=[]; +% end %Close all associated GUIs DATA.closeallnoguis(no); @@ -741,15 +768,54 @@ function closeimagestack(no) SET(noloop).Children = setdiff(SET(noloop).Children,family); end ind(family) = false; -if ~isempty(SET(no).Flow) - DATA.updateaxestables('flowremovestack',family); - DATA.updateaxestables('areaclearall'); +%correct global LVNO, RVNO and FlowNO + +resetLVNO=0; +resetRVNO=0; +resetFlowNO=0; +if not(isempty(DATA.LVNO)) + if any(family==DATA.LVNO) + resetLVNO=1; + elseif any(familylength(SET)) + DATA.LVNO = []; + resetLVNO = 1; +end +if not(isempty(DATA.RVNO)) && (DATA.RVNO<1 || DATA.RVNO>length(SET)) + DATA.RVNO = []; + resetRVNO = 1; +end +if not(isempty(DATA.FlowNO)) && (DATA.FlowNO<1 || DATA.FlowNO>length(SET)) + DATA.FlowNO = []; + resetFlowNO = 1; +end + %fix references for linked images linkfields = {'Parent' 'Children' 'Linked'}; +taggroup = zeros(1,length(SET)); for setloop = 1:length(SET) for i = 1:length(linkfields) @@ -777,70 +843,139 @@ function closeimagestack(no) if isfield(SET(setloop).StrainTagging,'cineno') if ismember(SET(setloop).StrainTagging.cineno,family) SET(setloop).StrainTagging.cineno = setloop; - SET(setloop).StrainTagging.cineupdated = true; + SET(setloop).StrainTagging.cineupdated = true; else - SET(setloop).StrainTagging.cineno = SET(setloop).StrainTagging.cineno - sum(family <= setloop); + increment = sum(family <= setloop); + if length(family) > 1 && increment == 1 + % increase increment to 2, because we are deleting a linked stack + increment = increment +1; + end + SET(setloop).StrainTagging.cineno = SET(setloop).StrainTagging.cineno - increment; end + % write value of cineno into the corresponding taggroup array + taggroup(1,setloop) = SET(setloop).StrainTagging.cineno; end end end +% cleanup taggroup +taggroup = (nonzeros(taggroup))'; +if ~isempty(taggroup) + for tagloop = taggroup + % write new taggroup into SET struct + SET(tagloop).StrainTagging.taggroup = taggroup; + end +end if isempty(SET) DATA.filecloseall_Callback(true); return; -end; - -%Take away from viewpanels -%zer = zeros(1,length(DATA.ViewPanels)); -tempind = not(DATA.ViewPanels==no); -DATA.ViewPanels = DATA.ViewPanels(tempind); -DATA.ViewPanelsType = DATA.ViewPanelsType(tempind); -DATA.ViewPanelsMatrix = DATA.ViewPanelsMatrix(tempind); -DATA.ViewIM = DATA.ViewIM(tempind); -DATA.Overlay = DATA.Overlay(tempind); -DATA.ViewMatrix = []; - -% %DATA.ViewPanels have internal references to old image stack ordering. -% for loop=1:length(DATA.ViewPanels) -% temp = DATA.ViewPanels(loop); -% if temp>0 -% newpos = zer; %zer frome above; -% newpos(temp) = 1; -% newpos = newpos(tempind); %tempind from above -% newpos = find(newpos); -% if ~isempty(newpos) -% DATA.ViewPanels(loop) = newpos; -% else -% DATA.ViewPanels(loop) = 0; -% end; -% end; -% end; +end -%update NO -if isempty(DATA.ViewPanels) || all(DATA.ViewPanels==0) - NO=1; -else - tmpno = DATA.ViewPanels(find(DATA.ViewPanels,1)); - if tmpno0 +% % newpos = zer; %zer frome above; +% % newpos(temp) = 1; +% % newpos = newpos(tempind); %tempind from above +% % newpos = find(newpos); +% % if ~isempty(newpos) +% % DATA.ViewPanels(loop) = newpos; +% % else +% % DATA.ViewPanels(loop) = 0; +% % end; +% % end; +% % end; +% +% %update NO +% if isempty(DATA.ViewPanels) || all(DATA.ViewPanels==0) +% NO=1; +% else +% tmpno = DATA.ViewPanels(find(DATA.ViewPanels,1)); +% if tmpno +function loadsegmentation_Callback(pathname,filename) %---------------------------------------------------- %Loads segmentation to current image stack from a .seg file. global DATA SET NO @@ -917,13 +1018,13 @@ function loadsegmentation_Callback(pathname,filename) %#ok if isequal(filename,0) mydisp('Load segmentation aborted by user'); return; - end; + end else if nargin<2 myfailed('Expected two input arguments.',DATA.GUI.Segment); return; - end; -end; + end +end SEG = []; try @@ -934,36 +1035,36 @@ function loadsegmentation_Callback(pathname,filename) %#ok myfailed('Could not load data. Data corrupted?',DATA.GUI.Segment); myworkoff; return; -end; +end if isempty(SEG) myfailed('The file did not contain any valid segmentation.',DATA.GUI.Segment); return; -end; +end %Change this check later if ~isempty(SEG.EndoX) if size(SEG.EndoX,3)~=SET(NO).ZSize myfailed('Number of slices must be the same as current number of slices.',DATA.GUI.Segment); return; - end; + end if size(SEG.EndoX,2)~=SET(NO).TSize myfailed('Number of timeframes must be the same as current number timeframes.',DATA.GUI.Segment); return; - end; -end; + end +end if str2num(removechars(SEG.ProgramVersion))>str2num(removechars(DATA.ProgramVersion)) %#ok mydisp('Warning, data has been generated with a later version that this program.'); -end; +end if str2num(removechars(SEG.ProgramVersion))<0.98 %#ok mydisp('File is older than v0.98'); is098 = true; else is098 = false; -end; +end try %--- Ok should be trustworthy now @@ -976,16 +1077,16 @@ function loadsegmentation_Callback(pathname,filename) %#ok else xofs = 0; yofs = 0; - end; + end else xofs = 0; yofs = 0; - end; + end else %Silent xofs = 0; yofs = 0; - end; + end SET(NO).EndoX = SEG.EndoX+xofs; SET(NO).EndoY = SEG.EndoY+yofs; @@ -993,7 +1094,7 @@ function loadsegmentation_Callback(pathname,filename) %#ok SET(NO).EpiY = SEG.EpiY+yofs; if is098 [SET(NO).EpiX,SET(NO).EpiY] = calcfunctions('resamplemodel',SET(NO).EpiX,SET(NO).EpiY,DATA.NumPoints); - end; + end SET(NO).EndoPinX = SEG.EndoPinX; %They are translated below. SET(NO).EndoPinY = SEG.EndoPinY; @@ -1050,52 +1151,52 @@ function loadsegmentation_Callback(pathname,filename) %#ok SET(NO).ImageType = 'General'; else SET(NO).ImageType = SEG.ImageType; - end; - end; + end + end if not(isfield(SEG,'OrgXSize')) if not(DATA.Silent) mywarning('Old file format did not contain original DICOM image size, guess on 256.',DATA.GUI.Segment); - end; + end SET(NO).OrgXSize = 256; SET(NO).OrgYSize = 256; SET(NO).OrgTSize = SET(NO).TSize; SET(NO).OrgZSize = SET(NO).ZSize; - end; + end if isfield(SEG,'ExcludePapilars') mydisp('Ignoring ExcludePapilars on imported segmentation'); % DATA.ExcludePapilars = SEG.ExcludePapilars; %set(DATA.Handles.excludepapilarscheckbox,'value',DATA.ExcludePapilars); - end; + end if isfield(SEG,'AutoLongAxis') SET(NO).AutoLongaxis = SEG.AutoLongaxis; - end; + end if isfield(SEG,'UseLight') mydisp('Ignoring UseLight on imported segmentation'); %DATA.UseLight = SEG.UseLight; %set(DATA.Handles.uselightcheckbox,'value',SEG.UseLight); - end; + end if isfield(SEG,'Scar') if not(DATA.Silent) mywarning('Contains scar data, loading not 100% supported yet.',DATA.GUI.Segment); - end; + end SET(NO).Scar = SEG.Scar; SET(NO).Scar.Mode = 'manualthreshold'; if not(isfield(SET(NO).Scar,'NoReflow')) SET(NO).Scar.NoReflow = repmat(uint8(0),size(SET(NO).Scar.Manual)); - end; - end; + end + end if isfield(SEG,'RVEndoX') SET(NO).RVEndoX = SEG.RVEndoX; SET(NO).RVEndoY = SEG.RVEndoY; SET(NO).RVEpiX = SEG.RVEpiX; SET(NO).RVEpiY = SEG.RVEpiY; - end; + end SET(NO).Longaxis = SEG.Longaxis; @@ -1104,40 +1205,40 @@ function loadsegmentation_Callback(pathname,filename) %#ok for zloop=1:SET(NO).ZSize SET(NO).EndoPinX{tloop,zloop} = SET(NO).EndoPinX{tloop,zloop}+xofs; SET(NO).EndoPinY{tloop,zloop} = SET(NO).EndoPinY{tloop,zloop}+yofs; - end; - end; - end; + end + end + end if ~isempty(SET(NO).EpiPinX) for tloop=1:SET(NO).TSize for zloop=1:SET(NO).ZSize SET(NO).EpiPinX{tloop,zloop} = SET(NO).EpiPinX{tloop,zloop}+xofs; SET(NO).EpiPinY{tloop,zloop} = SET(NO).EpiPinY{tloop,zloop}+yofs; - end; - end; - end; + end + end + end if ~isempty(SET(NO).RVEndoPinX) for tloop=1:SET(NO).TSize for zloop=1:SET(NO).ZSize SET(NO).RVEndoPinX{tloop,zloop} = SET(NO).RVEndoPinX{tloop,zloop}+xofs; SET(NO).RVEndoPinY{tloop,zloop} = SET(NO).RVEndoPinY{tloop,zloop}+yofs; - end; - end; - end; + end + end + end if ~isempty(SET(NO).RVEpiPinX) for tloop=1:SET(NO).TSize for zloop=1:SET(NO).ZSize SET(NO).RVEpiPinX{tloop,zloop} = SET(NO).RVEpiPinX{tloop,zloop}+xofs; SET(NO).RVEpiPinY{tloop,zloop} = SET(NO).RVEpiPinY{tloop,zloop}+yofs; - end; - end; - end; + end + end + end if isfield(SEG,'Rotated') SET(NO).Rotated = SEG.Rotated; - end; + end if isfield(SEG,'RoiN') SET(NO).RoiCurrent = SEG.RoiCurrent; @@ -1159,43 +1260,43 @@ function loadsegmentation_Callback(pathname,filename) %#ok SET(NO).Roi(loop).LineSpec = SEG.RoiLineSpec{loop}; end end - end; + end if isfield(SEG,'Measure') SET(NO).Measure = SEG.Measure; for loop=1:length(SET(NO).Measure) SET(NO).Measure(loop).X = SET(NO).Measure(loop).X+xofs; SET(NO).Measure(loop).Y = SET(NO).Measure(loop).Y+xofs; - end; - end; + end + end if isfield(SEG,'Point') SET(NO).Point = SEG.Point; SET(NO).Point.X = SET(NO).Point.X+xofs; SET(NO).Point.Y = SET(NO).Point.Y+yofs; - end; + end if isfield(SEG,'GEVENCSCALE') SET(NO).GEVENCSCALE = SEG.GEVENCSCALE; - end; + end catch me myfailed('Something went wrong during loading. Undoing...',DATA.GUI.Segment); mydispexception(me); tools('undosegmentation_Callback'); -end; +end if size(SET(NO).EndoDraged,1)~=SET(NO).TSize SET(NO).EndoDraged = repmat(SET(NO).EndoDraged(:),1,SET(NO).TSize); SET(NO).EpiDraged = repmat(SET(NO).EpiDraged(:),1,SET(NO).TSize); -end; +end %Prevent problems from old .seg files segment('checkconsistency',1:SET(NO).TSize,1:SET(NO).ZSize); -segment('updatemodeldisplay'); segment('updatevolume'); -segment('viewrefresh_Callback'); +%segment('viewrefresh_Callback'); +viewfunctions('setview') %--------------------- function quit_Callback(varargin) @@ -1203,20 +1304,27 @@ function quit_Callback(varargin) %Quit Segment global DATA SET NO -if length(varargin)>0 +if ~isempty(varargin) str = varargin{1}; else str = 'Closing software.'; end if ~isempty(DATA) - if DATA.quit - DATA.adduserevent(sprintf('%s\t%s\t%s\t%s', datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),str,'-')); - %DATA.adduserevent(['Time:' datestr(now,'yyyymmddHHMMSS')]) - saveguiposition(DATA.GUI.Segment); - segment('saveguipositiontodisk'); - - fig=DATA.fig; + if DATA.isSiemensVersion + % save results first + success = applysiemensoptions('savetosiemens_Callback',true); + if success + mydisp('Data was successfully saved'); + else + mydisp('Could not save data'); + end + applysiemensoptions('copyfinalresultstosyngovia'); + % move final results from temporal folder to the result folder + % delete possible report pdf + folderpath = getpreferencespath; + delete([folderpath filesep '*.pdf']) + fig = DATA.fig; DATA = []; SET = []; NO = []; @@ -1224,7 +1332,31 @@ function quit_Callback(varargin) clear SET clear NO delete(fig); %Call destroyer to take it down nice, see code => - close('all'); %Added do not know if it works. + %close('all'); %Added do not know if it works. + close all hidden % closes all figures, even the hidden ones + commandlinehelper('reset'); + else + if DATA.quit + DATA.adduserevent(sprintf('%s\t%s\t%s\t%s', datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),str,'-')); + %DATA.adduserevent(['Time:' datestr(now,'yyyymmddHHMMSS')]) + saveguiposition(DATA.GUI.Segment); + segment('saveguipositiontodisk'); + if DATA.Pref.UseCache && contains(DATA.ProgramName,'CMR') + cachefunctions('deletecache'); + end + fig = DATA.fig; + DATA = []; + SET = []; + NO = []; + clear DATA + clear SET + clear NO + delete(fig); %Call destroyer to take it down nice, see code => + %close('all'); %Added do not know if it works. + %close all hidden % closes all figures, even the hidden ones + close all force % closes all figures + commandlinehelper('reset'); + end end else delete(gcbo); diff --git a/source/findfunctions.m b/source/findfunctions.m index 74924bc..0f761ad 100644 --- a/source/findfunctions.m +++ b/source/findfunctions.m @@ -36,33 +36,33 @@ if nargout>3 varargout = cell(1,2); -end; +end if ~isfield(SET(1),'ImageType') SET(1).ImageType = ''; -end; +end %Check with image types first! for loop=1:length(SET) if isequal(lower(SET(loop).ImageType),'cine') cineno = [cineno loop]; %#ok - end; + end if isequal(lower(SET(loop).ImageType),'late enhancement') || ~isempty(SET(loop).Scar) scarno = [scarno loop]; %#ok - end; + end if isequal(lower(SET(loop).ImageType),'strain ffe') || isequal(lower(SET(loop).ImageType),'strain tfe') || ... ~isempty(SET(loop).Strain) || ... (~isempty(SET(loop).Flow) && isempty(SET(loop).Flow.PhaseNo) && ~isempty(SET(loop).Flow.PhaseX) && ~isempty(SET(loop).Flow.PhaseY) && isequal(SET(loop).Flow.MagnitudeNo,loop)) strainno = [strainno loop]; %#ok - end; + end if isequal(SET(loop).ImageType,'Flow (magnitude)') flowno = [flowno loop]; %#ok - end; + end if isequal(lower(SET(loop).ImageType),'perfusion rest') && ~isempty(SET(loop).MaR) marno = [marno loop]; %#ok - end; + end if isequal(lower(SET(loop).ImageType),'perfusion stress') && ~isempty(SET(loop).MaR) marno = [marno loop]; %#ok - end; + end % if nargout>3 % if isequal(SET(loop).ImageType,'Stress baseline'); @@ -72,9 +72,9 @@ if nargout>4 if isequal(lower(SET(loop).ImageType),'stress') varargout{2} = [varargout{2} loop]; - end; - end; -end; + end + end +end %Continue with trying to find with automatic for loop=1:length(SET) @@ -86,7 +86,7 @@ else if not(isempty(SET(loop).MaR)) && isempty(find(marno==loop,1)) marno = [marno loop]; %#ok - end; %not mar + end %not mar %If neither scar,flow check if short axes? %Note it may be both mar and cine! @@ -98,15 +98,65 @@ % (sum(sum(not(isnan([SET(loop).EndoX(:) SET(loop).EpiX(:) SET(loop).RVEndoX(:) SET(loop).RVEpiX(:)]))))>0)&&... % isempty(find(cineno==loop,1)) cineno = [cineno loop]; %#ok - end; - end; + end + end - end; %not flow - end; %not scar -end; + end %not flow + end %not scar +end + +%------------------------------------- +function [saxno, success] = findsaxno %#ok +%------------------------------------- +% find current stack with short axis image +global SET NO DATA +cineno = findfunctions('findno'); +saxno = find(strcmp({SET.ImageViewPlane},'Short-axis')); +zno = find([SET.ZSize] > 1); +saxno = intersect(cineno,union(saxno,zno)); +success = 1; +if isempty(saxno) + if ismember(NO,zno) && ~DATA.Silent &&... + yesno('Could not find image stack defined as Short-axis Cine. Use current stack?') + saxno = NO; + SET(saxno).ImageViewPlane = 'Short-axis'; + SET(saxno).ImageType = 'Cine'; + for p = find(DATA.ViewPanels==saxno) + drawfunctions('drawpanel',p); + end + elseif ismember(NO,zno) && DATA.Silent + saxno = NO; + SET(saxno).ImageViewPlane = 'Short-axis'; + SET(saxno).ImageType = 'Cine'; + else + if ~DATA.Silent + myfailed('Could not find short-axis image stack'); + end + success = 0; + return + end +end + +if ismember(NO,saxno) + saxno = NO; +else + nos = cellfun(@(x)dprintf('Short-axis stack %d',x), ... + num2cell(saxno),'UniformOutput',false); + if ~DATA.Silent + m = mymenu('Do segmentation on short-axis stack?', nos{:}); + else + m = 1; + end + if m + saxno = saxno(m); + else + success = 0; + return; + end +end %--------------------------------------------- -function cineshortaxisno = findcineshortaxisno(multiple) %#ok +function cineshortaxisno = findcineshortaxisno(multiple, minscore) %#ok %--------------------------------------------- %Find one [LV] or two [LV and RV] cine short axis stack global SET @@ -114,7 +164,9 @@ if nargin < 1 multiple = false; %default, only return one no, true = return all cine sax end - +if nargin < 2 + minscore = 0; % default value to return any cine slice +end %cineshortaxisno = []; [cineno] = findno; @@ -124,7 +176,7 @@ if isempty(cineno) cineshortaxisno = []; return; -end; +end %Find maximal number of slices maxslices = max(cat(1,SET(:).ZSize)); @@ -135,23 +187,57 @@ haslvseg = false(size(cineno)); hasrvseg = false(size(cineno)); hasmaxslices = ones(size(cineno)); +numberofsliceswithLV = zeros(size(cineno)); +numberofsliceswithRV = zeros(size(cineno)); for loop=1:length(cineno) iscine(loop) = isequal(lower(SET(cineno(loop)).ImageType),'cine') || (SET(cineno(loop)).TSize>=20 && ~strncmp(SET(cineno(loop)).ImageType,'Perfusion',9)); isshortaxis(loop) = isequal(lower(SET(cineno(loop)).ImageViewPlane),'short-axis'); haslvseg(loop) = (~isempty(SET(cineno(loop)).EndoX)|~isempty(SET(cineno(loop)).EpiX)); + if haslvseg(loop) + %check how many slices have lv segmentation + if ~isempty(SET(cineno(loop)).EndoX) + numberofsegmentedslices = findnumberofsegmentedslices(SET(cineno(loop)).EndoX); + else + numberofsegmentedslices = 0; + end + numberofsliceswithLV(loop) = numberofsliceswithLV(loop) + numberofsegmentedslices; + if ~isempty(SET(cineno(loop)).EpiX) + numberofsegmentedslices = findnumberofsegmentedslices(SET(cineno(loop)).EpiX); + else + numberofsegmentedslices = 0; + end + numberofsliceswithLV(loop) = numberofsliceswithLV(loop) + numberofsegmentedslices; + end hasrvseg(loop) = (~isempty(SET(cineno(loop)).RVEndoX)|~isempty(SET(cineno(loop)).RVEpiX)); + if hasrvseg(loop) + %check how many slices have lv segmentation + if ~isempty(SET(cineno(loop)).RVEndoX) + numberofsegmentedslices = findnumberofsegmentedslices(SET(cineno(loop)).RVEndoX); + else + numberofsegmentedslices = 0; + end + numberofsliceswithRV(loop) = numberofsliceswithRV(loop) + numberofsegmentedslices; + if ~isempty(SET(cineno(loop)).RVEpiX) + numberofsegmentedslices = findnumberofsegmentedslices(SET(cineno(loop)).RVEpiX); + else + numberofsegmentedslices = 0; + end + numberofsliceswithRV(loop) = numberofsliceswithRV(loop) + numberofsegmentedslices; + end + hasmaxslices(loop) = isequal(SET(cineno(loop)).ZSize,maxslices); -end; +end %Find if slices equals max %Choose the best candidate in order of priority. Each row in A is one %image stack, multiply with priority vector. Take largest sum. -A = [iscine' isshortaxis' haslvseg' hasrvseg' hasmaxslices']; - +A = [iscine' isshortaxis' haslvseg' numberofsliceswithLV' hasrvseg' numberofsliceswithRV' hasmaxslices']; +score = A*[16;12;4;1;2;1;1]; %most important in priority cine, shortaxis, lvseg, numberofslicesLV, rvseg, numberofslicesLV, maxslices + if multiple %find lv and rv stacks that is cine and short-axis - score = A*[16;8;4;2;1]; %most important in priority cine, shortaxis, lvseg, rvseg, maxslices + templvnos = find(haslvseg); temprvnos = find(hasrvseg); if ~isempty(templvnos) @@ -170,11 +256,32 @@ end cineshortaxisno = [lvno rvno]; else - score = A*[16;8;4;2;1]; %most important in priority cine, shortaxis, lvseg, rvseg, maxslices - [~,ind] = max(score); - cineshortaxisno = cineno(ind); +% score = A*[16;8;4;2;1]; %most important in priority cine, shortaxis, lvseg, rvseg, maxslices + [scorevalue,ind] = max(score); + if scorevalue < minscore + cineshortaxisno = []; + else + cineshortaxisno = cineno(ind); + end end +%------------------------------------------------ +function numberofsegmentedslices = findnumberofsegmentedslices(arraywithsegmentation) +%------------------------------------------------ +%Function to find number of slices in an 3D array +%(for example EndoX/EpiX/RVEndoX/RVEpiX)that contain segmentation + +% permuting array so that the slice dimension is the first one +arraywithsegmentation = permute(arraywithsegmentation,[3 1 2]); +% reshaping the array into 2D array with size [Number of Slices x rest] +arraywithsegmentation = reshape(arraywithsegmentation, size(arraywithsegmentation,1),[]); +% calculating whether each slice contains segmentation points +numberofpointsperslice = sum(~isnan(arraywithsegmentation),2); +% get the number of slices containing segmentations +numberofsegmentedslices = nnz(numberofpointsperslice); + + + %------------------------------------------------ function shortaxisno = findctshortaxisno(multiple) %#ok %------------------------------------------------ @@ -191,7 +298,7 @@ if isempty(ctno) shortaxisno = []; return; -end; +end %Find maximal number of slices maxslices = max(cat(1,SET(:).ZSize)); @@ -209,7 +316,7 @@ haslvseg(loop) = (~isempty(SET(ctno(loop)).EndoX)|~isempty(SET(ctno(loop)).EpiX)); hasrvseg(loop) = (~isempty(SET(ctno(loop)).RVEndoX)|~isempty(SET(ctno(loop)).RVEpiX)); hasmaxslices(loop) = isequal(SET(ctno(loop)).ZSize,maxslices); -end; +end %Find if slices equals max %Choose the best candidate in order of priority. Each row in A is one @@ -242,7 +349,6 @@ shortaxisno = ctno(ind); end - %---------------------------------------------------- function shortaxisno = findspectshortaxisno(multiple) %#ok %---------------------------------------------------- @@ -259,7 +365,7 @@ if isempty(spectno) shortaxisno = []; return; -end; +end %Find maximal number of slices maxslices = max(cat(1,SET(:).ZSize)); @@ -277,7 +383,7 @@ haslvseg(loop) = (~isempty(SET(spectno(loop)).EndoX)|~isempty(SET(spectno(loop)).EpiX)); hasrvseg(loop) = (~isempty(SET(spectno(loop)).RVEndoX)|~isempty(SET(spectno(loop)).RVEpiX)); hasmaxslices(loop) = isequal(SET(spectno(loop)).ZSize,maxslices); -end; +end %Find if slices equals max %Choose the best candidate in order of priority. Each row in A is one @@ -323,16 +429,16 @@ %Find best scar data to take. Take those with endo and scar data scar2use = zeros(size(scarno)); for sloop=1:length(scarno) - if existfunctions('existendo',scarno(sloop)); + if existfunctions('existendo',scarno(sloop)) scar2use(sloop) = scar2use(sloop)+0.5; end - if existfunctions('existepi',scarno(sloop)); + if existfunctions('existepi',scarno(sloop)) scar2use(sloop) = scar2use(sloop)+0.5; end - if not(isempty(SET(scarno(sloop)).Scar)); + if not(isempty(SET(scarno(sloop)).Scar)) scar2use(sloop) = scar2use(sloop)+4; end - if isequal(lower(SET(scarno(sloop)).ImageViewPlane),'short-axis'); + if isequal(lower(SET(scarno(sloop)).ImageViewPlane),'short-axis') scar2use(sloop) = scar2use(sloop)+2; end end @@ -345,15 +451,15 @@ for s = 1:length(scarno) if isempty(SET(scarno(s)).Scar) take(s) = false; - end; - end; + end + end scarno = scarno(take); if isempty(scarno) scarno = oldscarno; - end; + end if length(scarno)>1 - mywarning('Detected multiple scar data. Taking data with maximal scar volume (arbitrary decision)'); + %mywarning('Detected multiple scar data. Taking data with maximal scar volume (arbitrary decision)'); s = scarno(1); maxml = 0; for sloop = 1:length(scarno) @@ -362,16 +468,16 @@ if ml>maxml maxml = ml; s = scarno(sloop); - end; + end catch %#ok - end; - end; + end + end scarno = s; elseif length(scarno)>1 - mywarning('Detected multiple scar data. Taking first image stack (arbitrary decision)'); + disp('Detected multiple scar data. Taking first image stack (arbitrary decision)'); scarno = scarno(1); end -end; +end %------------------------------------------ function marno = findmarshortaxisno %#ok @@ -387,11 +493,11 @@ mar2use = false(size(marno)); for sloop=1:length(marno) mar2use(sloop) = existfunctions('existendo',marno(sloop)) && not(isempty(SET(marno(sloop)).MaR)) && max(SET(marno(sloop)).MaR.Percentage)>0; - end; + end marno = marno(mar2use); if length(marno)>1 - mywarning('Detected multiple MaR data. Taking data with maximal MaR volume (arbitrary decision)'); + disp('Detected multiple MaR data. Taking data with maximal MaR volume (arbitrary decision)'); s = marno(1); maxml = 0; for sloop = 1:length(marno) @@ -400,13 +506,13 @@ if ml>maxml maxml = ml; s = marno(sloop); - end; + end catch %#ok - end; - end; + end + end marno = s; - end; -end; + end +end %----------------------------------------- function [flowno,flowroi] = findflowaxisno(flowno) @@ -431,7 +537,7 @@ flow2use = false(size(flowno)); for sloop=1:length(flowno) flow2use(sloop) = (SET(flowno(sloop)).RoiN>0); - end; + end [maxval,maxind] = max(flow2use); allmax = find(flow2use == maxval); flowno = flowno(allmax); @@ -530,7 +636,7 @@ if isempty(SET(no).Scar) ind = false(SET(no).ZSize,1); return; -end; +end ind = squeeze(find(sum(sum(SET(no).Scar.Result(:,:,:)))~=0)); %-------------------------------------- @@ -546,7 +652,7 @@ if isempty(SET(no).MaR) ind = false(SET(no).ZSize,1); return; -end; +end if SET(no).TSize>1 ind = squeeze(find(sum(sum(sum(SET(no).MaR.Result(:,:,:,:))))~=0)); @@ -562,12 +668,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EndoX) ind = false(SET(no).ZSize,1); return; -end; +end if SET(no).TSize>1 temp = not(isnan(squeeze(SET(no).EndoX(1,:,:)))); @@ -575,10 +681,10 @@ ind = all(temp)'; else ind = sum(temp,1)'==SET(no).TSize; - end; + end else ind = squeeze(not(isnan(SET(no).EndoX(1,1,:)))); -end; +end %------------------------------------- function ind = findslicewithepiall(no) %#ok @@ -588,12 +694,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).EpiX) ind = false(SET(no).ZSize,1); return; -end; +end if SET(no).TSize>1 temp = not(isnan(squeeze(SET(no).EpiX(1,:,:)))); @@ -601,10 +707,10 @@ ind = all(temp)'; else ind = sum(temp,1)'==SET(no).TSize; - end; + end else ind = squeeze(not(isnan(SET(no).EpiX(1,1,:)))); -end; +end %--------------------------------------- function ind = findslicewithendo(no,tfs) %#ok @@ -622,17 +728,17 @@ if isempty(SET(no).EndoX) ind = false(SET(no).ZSize,1); return; -end; +end temp = not(isnan(squeeze(SET(no).EndoX(1,tfs,:)))); if length(tfs)>1 ind = (sum(temp,1)>0)'; if SET(no).ZSize==1 ind = max(ind(:)); - end; + end else ind = temp; -end; +end %------------------------------------- function ind = findslicewithrvendo(no,tfs) %#ok @@ -642,7 +748,7 @@ if nargin<1 no = NO; -end; +end if nargin < 2 tfs = 1:SET(no).TSize; end @@ -650,17 +756,17 @@ if isempty(SET(no).RVEndoX) ind = false(SET(no).ZSize,1); return; -end; +end temp = not(isnan(squeeze(SET(no).RVEndoX(1,tfs,:)))); if length(tfs)>1 ind = (sum(temp,1)>0)'; if SET(no).ZSize==1 ind = max(ind(:)); - end; + end else ind = temp; -end; +end %-------------------------------------- function ind = findslicewithrvendoall(no) %#ok @@ -670,12 +776,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).RVEndoX) ind = false(SET(no).ZSize,1); return; -end; +end if SET(no).TSize>1 temp = not(isnan(squeeze(SET(no).RVEndoX(1,:,:)))); @@ -683,15 +789,343 @@ ind = all(temp); else ind = sum(temp,1)==SET(no).TSize; - end; + end else ind = squeeze(not(isnan(SET(no).RVEndoX(1,1,:)))); -end; +end + + +%--------------------- +function [measureind, pointind,measurex,measurey,measurez,mindist] = closestmeasure(panel,xclick,yclick) +%----------------------- +%finds the closest visible measure. returns the index of the point within +%the closest measure aswell as all corrdinates for the closest measure. +global DATA SET + +no = DATA.ViewPanels(panel); +%No measures avaiable +if isempty(SET(no).Measure) + measureind = []; + pointind = []; + measurex = []; + measurey = []; + measurez = []; + mindist = inf; + return +end + +%retrieve coordinates of measures in panel +[measure,~] = viewfunctions('getmeasurecoords',panel); + +%find which meaures to consider +slicestodo = viewfunctions('slicesinpanel',panel); +measurestocheck = find(cellfun(@(x,y) any(ismember(x,slicestodo)) && ... + any(y==SET(no).CurrentTimeFrame) ,... + {measure.Z},{measure.T})); + +measurex = cell(1,length(measurestocheck)); +measurey = measurex; +measurez = measurex; + +for i = 1:length(measurestocheck) + measurex{i} = measure(measurestocheck(i)).X; + measurey{i} = measure(measurestocheck(i)).Y; + measurez{i} = measure(measurestocheck(i)).Z; +end + +if ~isempty(DATA.LastClickType) && strcmp(DATA.LastClickType ,'alt') + [mindists,mininds] = cellfun(@(x,y) min(calcfunctions('calcdistpointoline',[xclick yclick 0],x,y)),measurey,measurex); +else + [mindists,mininds] = cellfun(@(x,y) min(sqrt((xclick-x).^2+(yclick-y).^2)),measurey,measurex); +end +[mindist,ind] = min(mindists); + +if mindist +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); + +if nargin<4 + slice = SET(no).CurrentSlice;%clickedslice(panel); +end + +if nargin<5 + tf = SET(no).CurrentTimeFrame; +end + +minendo = dist2contour('Endo',no,x,y,slice,tf); +minepi = dist2contour('Epi',no,x,y,slice,tf); +minrvendo = dist2contour('RVEndo',no,x,y,slice,tf); +minrvepi = dist2contour('RVEpi',no,x,y,slice,tf); +if strcmp(DATA.ProgramName, 'Segment') + mincenter = min(sqrt((SET(no).CenterX-x).^2+(SET(no).CenterY-y).^2)); +else + mincenter = Inf; +end + +%this is the code to find closest measure +[measureind, ~,~,~,~,minmeasure] = closestmeasure(panel,y,x); + +%Find closest roi in current timeframe and slice +[minroi,roiind] = closestroi(panel,x,y,slice,tf); + +%Find closest point in current timeframe and slice +[minpoint,pointind] = closestpoint(panel,x,y,slice,tf); + +%Find closest interp +[minendointerp,endointerpind] = closestinterp(panel,'EndoInterp',x,y,slice,tf); +[minepiinterp,epiinterpind] = closestinterp(panel,'EpiInterp',x,y,slice,tf); +[minrvendointerp,rvendointerpind] = closestinterp(panel,'RVEndoInterp',x,y,slice,tf); +[minrvepiinterp,rvepiinterpind] = closestinterp(panel,'RVEpiInterp',x,y,slice,tf); + +%summarize which is closest +dists = [minmeasure,minroi,minendo,minepi,minrvendo,minrvepi,... + minendointerp,minepiinterp,minrvendointerp,minrvepiinterp,minpoint,mincenter]; + +[mindist,typeind] = min(dists); + +types = {'Measure','Roi','Endo','Epi','RVEndo','RVEpi','EndoInterp',... + 'EpiInterp','RVEndoInterp','RVEpiInterp','Point', 'Center'}; + +type = types{typeind}; + +%If selected type is contour then check if Interp is within intervall and +%set Interp version of contour as type +if typeind>2 && typeind<7 && dists(typeind+4)<=DATA.Pref.ContourAdjustDistance %preference dist to object + type = types{typeind+4}; +end + +%if smallest distance is more than contour adjust distance then return +%image type for context menu +if mindist >DATA.Pref.ContourAdjustDistance + type = 'Image'; +end + +%if the closest clicked item is a measure roi or interp point return index to SET struct location +switch type + case 'Measure' + objind = measureind; + case 'Roi' + objind = roiind; + case 'EndoInterp' + objind = endointerpind; + case'EpiInterp' + objind = epiinterpind; + case'RVEndoInterp' + objind = rvendointerpind; + case 'RVEpiInterp' + objind = rvepiinterpind; + case 'Point' + objind = pointind; + otherwise %objind is irrelevant + objind = 0; +end + + +%------------------------------ +function [dist,ind] = closestpoint(panel,x,y,slice,tf) +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); + +if nargin < 4 + slice = SET(no).CurrentSlice; +end + +if nargin < 5 + tf = SET(no).CurrentTimeFrame; +end + +if ismember(DATA.ViewPanelsType{panel},{'trans3DP','viewport','sag3DP','cor3DP'}) + %If 3DP then all slices + xi = SET(no).Point.X; + yi = SET(no).Point.Y; + zi = SET(no).Point.Z; + [dist,ind] = min(sqrt((x-xi).^2+(y-yi).^2+(slice-zi).^2)); + +else + %get coordinates of all relevant points + if not(isempty(SET(no).Point.X)) + pointstodo = find(ismember(SET(no).Point.Z,slice)&... + (ismember(SET(no).Point.T,tf)|isnan(SET(no).Point.T))); %nan means constant over time + xi = SET(no).Point.X(pointstodo); + yi = SET(no).Point.Y(pointstodo); + else + dist = inf; + ind = []; + return + end + + %Compute distance + [dist,ind] = min(sqrt((x-xi).^2+(y-yi).^2)); + ind = pointstodo(ind); + +end + + +%------------------------------ +function [dist,ind,pointsinslice] = closestpoint3dp(panel,x,y,slice) %#ok +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); + +%get coordinates of all relevant points +if not(isempty(SET(no).Point)) + %convert xyslice so that we can compare it to the point coordinates + [r,g,b] = segment3dp.tools('xyz2rgb',SET(no).Point.X,SET(no).Point.Y,SET(no).Point.Z); + + %also get clicked position rgb coordinates + [rc,gc,bc] = segment3dp.tools('xyz2rgb',x,y,slice); + + %Then find slice match and compare distance in slice plane for closest + %point + switch DATA.ViewPanelsType{panel} + case 'trans3DP' + pointstodo = find(round(r) == slice); + [dist,ind] = min(sqrt((gc-g(pointstodo)).^2+(bc-b(pointstodo)).^2)); + case 'sag3DP' + pointstodo = find(round(g) == slice); + [dist,ind] = min(sqrt((rc-r(pointstodo)).^2+(bc-b(pointstodo)).^2)); + case 'cor3DP' + pointstodo = find(round(b) == slice); + [dist,ind] = min(sqrt((gc-g(pointstodo)).^2+(rc-r(pointstodo)).^2)); + end +else + dist = inf; + ind = []; + return +end + +ind = pointstodo(ind); + +if nargout == 3 + pointsinslice = pointstodo; +end + +%------------------------------ +function [dist,ind] = closestinterp(panel,type,x,y,slice,tf) +%----------------------- +global DATA SET + +no = DATA.ViewPanels(panel); + +if nargin<5 + slice = SET(no).CurrentSlice;%clickedslice(panel); +end + +if nargin<6 + tf = SET(no).CurrentTimeFrame; +end + +if isempty(SET(no).([type,'X'])) ||... + isempty(SET(no).([type,'X']){tf,slice}) + dist = inf; + ind = []; + return +end + +xi = SET(no).([type,'X']){tf,slice}; +yi = SET(no).([type,'Y']){tf,slice}; +[dist,ind] = min(sqrt((x-xi).^2+(y-yi).^2)); + + +%-------------------------------------------------------------------------- +function [dist,roiind,pointind] = closestroi(panel,xclick,yclick,slice,tf,no) +%-------------------------------------------------------------------------- +%The input coordinates are presumed to be in the same coordinate system as +%the stored rois i.e you need to scale and translate your input. pointind +%is optional and is the index of the closest point on the closest roi. + +global DATA SET + +if nargin<6 + no = DATA.ViewPanels(panel); +end + +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + no = SET(no).Flow.MagnitudeNo; +end + +if nargin<4 || isempty(slice) + slice = SET(no).CurrentSlice;%clickedslice(panel); +end + +if nargin<5 || isempty(tf) + tf = SET(no).CurrentTimeFrame; +end + +roistodo = find(cellfun(@(x,y) ~isempty(x) && ... + any(x==slice) && any(y==tf)... + ,{SET(no).Roi.Z},{SET(no).Roi.T})); + +roix = cell(1,length(roistodo)); +roiy = cell(1,length(roistodo)); + +for i = 1:length(roistodo) + roix{i} = SET(no).Roi(roistodo(i)).X(:,tf); + roiy{i} = SET(no).Roi(roistodo(i)).Y(:,tf); +end + +%Find closest roi in current timeframe and slice +[dist,ind] = cellfun(@(x,y) min(sqrt((xclick-x).^2+(yclick-y).^2)),roix,roiy); +[~,ind_tmp] = min(dist); +dist = dist(ind_tmp); +roiind = roistodo(ind_tmp); + +if isempty(dist) || isnan(dist) + dist = inf; +end + +if nargout == 3 + pointind = ind(ind_tmp); +end %---------------------------------- function ind = findslicewithepi(no,tfs) %#ok %---------------------------------- -%Find slices with endocard in any timeframe +%Find slices with epicard in any timeframe global SET NO if nargin<1 @@ -704,42 +1138,46 @@ if isempty(SET(no).EpiX) ind = false(SET(no).ZSize,1); return; -end; +end temp = not(isnan(squeeze(SET(no).EpiX(1,tfs,:)))); if length(tfs)>1 ind = (sum(temp,1)>0)'; if SET(no).ZSize==1 ind = max(ind(:)); - end; + end else ind = temp; -end; +end %------------------------------------ -function ind = findslicewithrvepi(no) %#ok +function ind = findslicewithrvepi(no,tfs) %#ok %------------------------------------ %Find slices with RV epicard in any timeframe global SET NO if nargin<1 no = NO; -end; +end + +if nargin < 2 + tfs = 1:SET(no).TSize; +end if isempty(SET(no).RVEpiX) ind = false(SET(no).ZSize,1); return; -end; +end -temp = not(isnan(squeeze(SET(no).RVEpiX(1,:,:)))); -if SET(no).TSize>1 +temp = not(isnan(squeeze(SET(no).RVEpiX(1,tfs,:)))); +if length(tfs)>1 ind = (sum(temp,1)>0)'; if SET(no).ZSize==1 ind = max(ind(:)); - end; + end else ind = temp; -end; +end %-------------------------------------- function ind = findslicewithrvepiall(no) %#ok @@ -749,12 +1187,12 @@ if nargin<1 no = NO; -end; +end if isempty(SET(no).RVEpiX) ind = false(SET(no).ZSize,1); return; -end; +end if SET(no).TSize>1 temp = not(isnan(squeeze(SET(no).RVEpiX(1,:,:)))); @@ -762,10 +1200,10 @@ ind = all(temp); else ind = sum(temp,1)==SET(no).TSize; - end; + end else ind = squeeze(not(isnan(SET(no).RVEpiX(1,1,:)))); -end; +end %-------------------------------- function [x,y] = findlvcenter(no,slices) %#ok @@ -792,7 +1230,7 @@ autocropfailed=true; else maxdistfromcenter=140;%mm %estimate to (half) the radius of a large heart, half is enough but full to have a margin -end; +end %Takes some midventricular slices len = 50/2; %50 is 50mm @@ -848,7 +1286,7 @@ imagesc(cutim(:,:,1,1)); axis image off; colorbar -end; +end %Find percentile sorted = sort(cutim(:)); @@ -906,9 +1344,9 @@ autocropfailed log(loop) = dist; %mark as candidate by setting distance end - end; - end; -end; + end + end +end %Find closest candidate, i.e smallest number [~,pos] = sort(log); %sort @@ -933,7 +1371,7 @@ plot(y,x,'rd'); hold off; axis image off -end; +end %-------------------------------- function [x,y] = findrvcenter(no,slices) %#ok @@ -949,17 +1387,48 @@ y = SET(no).CenterY; %------------------------------------------------- -function tfs = findframeswithsegmentation(type,no) %#ok +function tfs = findframeswithsegmentation(type,no,slices) %#ok %------------------------------------------------- %Find timeframes in no containing segmentation of type global SET -switch type - case 'endo' - tfs = squeeze(~all(isnan(SET(no).EndoX(1,:,:)),3)); - case 'epi' - tfs = squeeze(~all(isnan(SET(no).EpiX(1,:,:)),3)); +if nargin ==2 + slices = 1:SET(no).ZSize; end + +contourx = SET(no).([type,'X']); + +if ~isempty(contourx) + tfs = squeeze(~all(isnan(contourx(1,:,slices)),3)); +else + tfs = zeros(1,SET(no).TSize); + return +end + +%------------------------------------------------- +function tfs = findframeswithinterpolationpoints(type,no,slices) %#ok +%------------------------------------------------- +%Find timeframes in no containing segmentation of type +global SET + +if nargin ==2 + slices = 1:SET(no).ZSize; +end + +if isempty(SET(no).([type,'InterpX'])) + tfs = zeros(1,SET(no).TSize); +else + tfs = ~cellfun(@isempty,SET(no).([type,'InterpX'])(:,slices)); +end + +if ~isrow(tfs) + tfs = tfs'; +end + +if size(tfs,1)>1 + tfs = any(tfs); +end + %--------------------------------------- function [ind] = findoutflowtractslices(no,tfs) %#ok @@ -970,7 +1439,7 @@ if (SET(no).ResolutionX+SET(no).ResolutionY)/2<0.5 warning('The threshold to find outflow tract (2mm) is species dependent, and might be incorrect for this images.'); -end; +end sectors=24; %we use a 24 sector model tresh=2; %2 mm threshold of wall thickness for slice to be considered outflow tract @@ -986,7 +1455,7 @@ if isempty(SET(no).EndoX) && isempty(SET(no).EpiX) ind = false(SET(no).ZSize,1); return; -end; +end wallthickness = calcfunctions('calcwallthickness', sectors,no); wallthickness=wallthickness(:,:,tfs); @@ -1001,9 +1470,9 @@ for zloop=1:pos %loop to the last found one if ind(zloop) element = true; %As soon as found one, start putting ones - end; + end ind(zloop) = element; -end; +end %------------------------------- @@ -1013,11 +1482,11 @@ function setstack_Callback(type) %#ok global DATA SET switch type case 'flow' - stri = 'Select image stack for flow report'; + stri = dprintf('Select image stack for flow report'); case 'lv' - stri = 'Select image stack for LV report'; + stri = dprintf('Select image stack for LV report'); case 'rv' - stri = 'Select image stack for RV report'; + stri = dprintf('Select image stack for RV report'); end menuitems = cell(1,1); nn = 1; @@ -1031,7 +1500,7 @@ function setstack_Callback(type) %#ok end end -menuitems{nn} = sprintf('Unselect'); +menuitems{nn} = dprintf('Unselect'); s = mymenu(stri,menuitems); if ~isempty(s) && s~=0 @@ -1041,24 +1510,38 @@ function setstack_Callback(type) %#ok case 'flow' DATA.FlowNO = []; DATA.FlowROI = []; + if isfield(DATA.Handles,'flowstackpushbutton') + set(DATA.Handles.flowstackpushbutton,'String',dprintf('Set Stack')); + end case 'lv' DATA.LVNO = []; + if isfield(DATA.Handles,'lvstackpushbutton') + set(DATA.Handles.lvstackpushbutton,'String',dprintf('Set Stack')); + end case 'rv' DATA.RVNO = []; + if isfield(DATA.Handles,'rvstackpushbutton') + set(DATA.Handles.rvstackpushbutton,'String',dprintf('Set Stack')); + end end else no = stacks(s); switch type case 'flow' - if SET(no).TSize == 1 || isempty(SET(no).Flow) || isempty(SET(no).Flow.Result) + if SET(no).TSize == 1 || isempty(SET(no).Flow) %|| isempty(SET(no).Flow.Result) myfailed('Flow image stack need to be time resolved and contain flow analysis.',DATA.GUI.Segment); DATA.FlowNO = []; DATA.FlowROI = []; + if isfield(DATA.Handles,'flowstackpushbutton') + set(DATA.Handles.flowstackpushbutton,'String',dprintf('Set Stack')); + end else DATA.FlowNO = no; [~,flowroi] = findflowaxisno(no); %identify flow ROI based on ROI names DATA.FlowROI = flowroi; - set(DATA.Handles.flowstackpushbutton,'String',sprintf('Stack #%d',no)); + if isfield(DATA.Handles,'flowstackpushbutton') + set(DATA.Handles.flowstackpushbutton,'String',dprintf('Stack #%d',no)); + end end case 'lv' %If longaxis no then we need to find the appropriate set. will use @@ -1067,33 +1550,44 @@ function setstack_Callback(type) %#ok LAX_group = findlaxset; if all(LAX_group==0) DATA.LVNO = no; - set(DATA.Handles.lvstackpushbutton,'String',sprintf('Stack #%d',no)); + if isfield(DATA.Handles,'lvstackpushbutton') + set(DATA.Handles.lvstackpushbutton,'String',dprintf('Stack #%d',no)); + end else LAX_group = LAX_group(LAX_group~=0); DATA.LVNO = LAX_group; - str = [num2str(LAX_group(1)),',',num2str(LAX_group(2)),',',num2str(LAX_group(3))]; - set(DATA.Handles.lvstackpushbutton,'String',sprintf('Stack #%s',str)); + str = []; + for i = 1:length(LAX_group) + str = [str, num2str(LAX_group(i)),',']; + end + str(end) = []; + if isfield(DATA.Handles,'lvstackpushbutton') + set(DATA.Handles.lvstackpushbutton,'String',dprintf('Stack #%s',str)); + end end else DATA.LVNO = no; - set(DATA.Handles.lvstackpushbutton,'String',sprintf('Stack #%d',no)); + if isfield(DATA.Handles,'lvstackpushbutton') + set(DATA.Handles.lvstackpushbutton,'String',dprintf('Stack #%d',no)); + end end case 'rv' DATA.RVNO = no; - set(DATA.Handles.rvstackpushbutton,'String',sprintf('Stack #%d',no)); + if isfield(DATA.Handles,'rvstackpushbutton') + set(DATA.Handles.rvstackpushbutton,'String',dprintf('Stack #%d',no)); + end end end end switch type case 'flow' - DATA.flowreportupdate; - DATA.updateflowaxes; + segment('updateflow'); case {'lv','rv'} - segment('updatevolume',true) - DATA.volumereportupdate; - DATA.updatevolumeaxes; + segment('updatevolume',true); end + + %------------------------------------------------------ function saxno = findctsaxwithsegmentation(type) %----------------------------------------------------- @@ -1163,7 +1657,7 @@ function setstack_Callback(type) %#ok %----------------------------------------------------- -function LAX_group = findlaxset +function LAX_group = findlaxset(segmentationatedes) %----------------------------------------------------- % Code for finding single slice LAX set with endo segmentation. Data is returned % as [CH2, CH3, CH4], temporary data vector if no chamber can be found @@ -1172,18 +1666,30 @@ function setstack_Callback(type) %#ok LAX_group=[0 0 0]; %% [CH2, CH3, CH4], temporary data vector +if nargin == 0 + segmentationatedes = 0; +end + for loop = 1:length(SET) - if(strcmp(SET(loop).ImageViewPlane,'2CH')&& SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && not(isempty(SET(loop).EndoX))) + if segmentationatedes + validchecks = SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && ... + not(isempty(SET(loop).EndoX)) && ~all(isnan(SET(loop).EndoX(:,SET(loop).EDT))) && ~all(isnan(SET(loop).EndoX(:,SET(loop).EST))); + else + validchecks = SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && ... + not(isempty(SET(loop).EndoX)); + end + + if strcmp(SET(loop).ImageViewPlane,'2CH')&& validchecks%SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && not(isempty(SET(loop).EndoX))) if (LAX_group(1)== 0) LAX_group(1)=loop; end end - if(strcmp(SET(loop).ImageViewPlane,'3CH')&& SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && not(isempty(SET(loop).EndoX))) + if strcmp(SET(loop).ImageViewPlane,'3CH')&& validchecks%SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && not(isempty(SET(loop).EndoX))) if (LAX_group(2)== 0) LAX_group(2)=loop; end end - if(strcmp(SET(loop).ImageViewPlane,'4CH')&& SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && not(isempty(SET(loop).EndoX))) + if strcmp(SET(loop).ImageViewPlane,'4CH')&& validchecks%SET(loop).ZSize==1 && isempty(SET(loop).StrainTagging) && not(isempty(SET(loop).EndoX))) if (LAX_group(3)== 0) LAX_group(3)=loop; end diff --git a/source/findscu.exe b/source/findscu.exe index efd2d2b..338da72 100644 Binary files a/source/findscu.exe and b/source/findscu.exe differ diff --git a/source/findsliceuniquetimeframes.m b/source/findsliceuniquetimeframes.m new file mode 100644 index 0000000..93458f9 --- /dev/null +++ b/source/findsliceuniquetimeframes.m @@ -0,0 +1,26 @@ +function outdcms = findsliceuniquetimeframes(mydcms) + +%unqdcms = []; +%mydir = dir([dicompath filesep '*.dcm']); +%mydcms = {mydir.name}; +ttt = zeros(1,numel(mydcms)); +numdcms = numel(mydcms); +wb = mywaitbarstart(numdcms,'Searching for files that do not match slice/phase.'); +for i = 1:numdcms + mytags = segdicomread_mex({[mydcms{i}]}); + ttt(i) = str2double(char(mytags{1}.AcquisitionTime)); + wb = mywaitbarupdate(wb); +end +mywaitbarclose(wb); + +unqt = unique(ttt); +thist = hist(ttt,unqt); +unqs = find(thist < max(thist)); +unqdcms = {}; +for i = unqs + if numel(i) == 1 + unqdcms = [unqdcms mydcms(ttt == unqt(i))]; + end +end + +outdcms = setdiff(mydcms,unqdcms); \ No newline at end of file diff --git a/source/flow.fig b/source/flow.fig index 328d628..08694f3 100644 Binary files a/source/flow.fig and b/source/flow.fig differ diff --git a/source/flow.p b/source/flow.p index c63278e..35f569e 100644 Binary files a/source/flow.p and b/source/flow.p differ diff --git a/source/floweddycurrent.m b/source/floweddycurrent.m index 58d0d16..7390616 100644 --- a/source/floweddycurrent.m +++ b/source/floweddycurrent.m @@ -6,7 +6,7 @@ if nargin==0 init; return; -end; +end macro_helper(varargin{:}); [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard @@ -22,12 +22,12 @@ function init(plotonok) [ok,no] = safetychecks; if ~ok return; -end; +end %Check if we should plot after user press ok if nargin<1 plotonok = false; -end; +end %Initalize DATA.GUI.EddyCurrent = mygui('floweddycurrent.fig'); @@ -35,7 +35,7 @@ function init(plotonok) initvariables(no); gui.plotonok = plotonok; - +set(gui.fig, 'Pointer','arrow') %Initialize graphics graphicalinit; @@ -56,19 +56,19 @@ function initsmall(plotonok) %#ok [ok,no] = safetychecks; if ~ok return; -end; +end %Check if we should plot after user press ok if nargin<1 plotonok = false; -end; +end %Initalize DATA.GUI.EddyCurrent = mygui('floweddycurrentsmall.fig'); gui = DATA.GUI.EddyCurrent; %Hide gui -set(gui.fig,'visible','off'); +%set(gui.fig,'visible','off'); initvariables(no); gui.biggui = false; %Mark that the smaller GUI @@ -81,7 +81,7 @@ function initsmall(plotonok) %#ok recalculate_Callback; %This also calls update %Show GUI -set(gui.fig,'visible','on'); +set(gui.fig,'visible','on','Pointer','arrow'); %------------------------- function initvariables(no) @@ -101,7 +101,7 @@ function initvariables(no) gui.biggui = true; %When true it is the main gui which is initialized. gui.ignorerois = false; %If true then we do not care about stationary tissue or non stationary tissue -if isfield(SET(gui.phaseno).Flow, 'PhaseCorrRemoveBadFit'); +if isfield(SET(gui.phaseno).Flow, 'PhaseCorrRemoveBadFit') gui.usebadfit = SET(gui.phaseno).Flow.PhaseCorrRemoveBadFit; else gui.usebadfit = true; @@ -109,23 +109,23 @@ function initvariables(no) if ~isfield(SET(gui.phaseno).Flow,'PhaseCorr') SET(gui.no).Flow.PhaseCorr = []; -end; +end if ~isfield(SET(gui.phaseno).Flow,'PhaseCorrPercentiles') SET(gui.phaseno).Flow.PhaseCorrPercentiles = 0.6; -end; +end if ~isfield(SET(gui.phaseno).Flow,'PhaseCorrMagnitudeThreshold') SET(gui.phaseno).Flow.PhaseCorrMagnitudeThreshold = 0.1; -end; +end if ~isfield(SET(gui.phaseno).Flow,'PhaseCorrMethod') SET(gui.phaseno).Flow.PhaseCorrMethod = 'linear'; -end; +end if ~isfield(SET(gui.phaseno).Flow,'PhaseCorrTimeResolved') SET(gui.phaseno).Flow.PhaseCorrTimeResolved = false; -end; +end if ~isfield(SET(gui.phaseno).Flow,'PhaseCorrStaticTissueRois') SET(gui.phaseno).Flow.PhaseCorrStaticTissueRois = false; -end; +end %--------------------- function graphicalinit @@ -138,7 +138,7 @@ function initvariables(no) %This function only updates the big gui if ~gui.biggui return; -end; +end %Update boxes, sliders etc. set(gui.handles.phaseslider,'Value',100*SET(gui.phaseno).Flow.PhaseCorrPercentiles); @@ -164,7 +164,7 @@ function initvariables(no) otherwise myfailed(dprintf('Unknown method %s.',SET(gui.phaseno).Flow.PhaseCorrMethod)); return; -end; +end set(gui.handles.methodlistbox,'value',v); set(gui.handles.timeresolvedcheckbox,'value',double(SET(gui.phaseno).Flow.PhaseCorrTimeResolved)); set(gui.handles.statictissueroischeckbox,'value',double(SET(gui.phaseno).Flow.PhaseCorrStaticTissueRois)); @@ -174,12 +174,12 @@ function initvariables(no) set(gui.handles.sliceslider,'min',1,'max',SET(gui.phaseno).ZSize,'value',gui.slice); else set([gui.handles.slicetext gui.handles.sliceslider],'visible','off'); -end; +end set(gui.handles.timeslider,'min',1,'max',SET(gui.phaseno).TSize,'value',gui.timeframe); if ~SET(gui.phaseno).Flow.PhaseCorrTimeResolved set([gui.handles.timetext gui.handles.timeslider],'visible','off'); -end; +end %------------------------------- function [res,no] = safetychecks @@ -199,7 +199,7 @@ function initvariables(no) if isempty(SET(NO).Flow) myfailed('No flow data.'); return; -end; +end if isequal(NO,SET(NO).Flow.MagnitudeNo) %Check if only one phase is available. @@ -212,8 +212,8 @@ function initvariables(no) else myfailed('Can not do eddy current compensation on magnitude image with multiple phase images. Select a phase image stack.'); return; - end; -end; + end +end %If this statement is reached then ok. res = true; @@ -236,7 +236,7 @@ function initvariables(no) recalculate_Callback; %--------------------------- -function timeslider_Callback %#ok +function timeslider_Callback %--------------------------- %Timeslider Callback @@ -253,7 +253,7 @@ function initvariables(no) else set([gui.handles.timetext gui.handles.timeslider],'visible','off'); gui.timeframe = 1; -end; +end update; @@ -308,7 +308,7 @@ function initvariables(no) gui.slice = min(max(round(gui.handles.slice),1),SET(gui.phaseno).ZSize); else gui.slice = 1; -end; +end update; @@ -330,7 +330,7 @@ function initvariables(no) SET(gui.phaseno).Flow.PhaseCorrMethod = 'quadratic'; case 3 SET(gui.phaseno).Flow.PhaseCorrMethod = 'ge'; -end; +end recalculate_Callback; @@ -441,23 +441,23 @@ function initvariables(no) %experiment. type = ''; - if isequal(SET(no).Flow.PhaseX,no); + if isequal(SET(no).Flow.PhaseX,no) type = 'x'; - end; + end - if isequal(SET(no).Flow.PhaseY,no); + if isequal(SET(no).Flow.PhaseY,no) type = 'y'; - end; + end - if isequal(SET(no).Flow.PhaseNo,no); + if isequal(SET(no).Flow.PhaseNo,no) type = 'z'; - end; + end if isempty(type) myfailed(dprintf('Could not determine direction of flow (x,y,z).')); myworkoff; return; - end; + end %--- Find corresponding phase image point = SET(no).ImagePosition; @@ -474,16 +474,16 @@ function initvariables(no) case 'x' if isequal(SET(loop).Flow.PhaseX,loop) candidate = true; - end; + end case 'y' if isequal(SET(loop).Flow.PhaseY,loop) candidate = true; - end; + end case 'z' if isequal(SET(loop).Flow.PhaseNo,loop) candidate = true; - end; - end; + end + end if candidate tempdir = cross(... @@ -496,12 +496,12 @@ function initvariables(no) if abs(sum(point(:).*tempdir(:))-d)<1e-4 %The point fits in this plane, add it!. match = [match loop]; %#ok - end; - end; + end + end - end; %not same magnitude - end; %Flow data set - end; %Loop over image stacks + end %not same magnitude + end %Flow data set + end %Loop over image stacks if isempty(match) myfailed(dprintf('No matches found.')); @@ -509,33 +509,32 @@ function initvariables(no) try set(gui.handles.methodlistbox,'value',1); catch - end; + end myworkoff; return; - end; + end %Create cell array matchcell = cell(1,length(match)); for loop=1:length(match) matchcell{loop} = match(loop); - end; + end if length(match)>1 - mywarning(dprintf('More than one plane candidate found.')); - m = mymenu('Choose image stack',mathcell); + m = mymenu('More than one plane candidate found. Choose image stack',mathcell); else m = 1; - end; + end if isequal(m,0) myfailed(dprintf('Aborted.')); myworkoff; return; - end; + end match = match(m); - gui.phasecorr = 0.5-SET(match).IM; + gui.phasecorr = SET(match).IM-0.5; %Changed 2021-03-25 after being notified by Erik Andreas Rye Berg . Checked it was incorrect: was 0.5-SET(match).IM; gui.logim = SET(SET(match).Flow.MagnitudeNo).IM(:,:,1)>0.05; %ge limit temp = gui.phasecorr; @@ -556,8 +555,8 @@ function initvariables(no) for rloop=1:SET(gui.magno).RoiN if isequal(SET(gui.magno).Roi(rloop).Name,'Static tissue') rois = [rois rloop]; %#ok - end; - end; + end + end if isempty(rois) myfailed(dprintf('No static tissue regions marked.')); @@ -567,21 +566,44 @@ function initvariables(no) catch end return; - end; + end gui.logim = false([SET(no).XSize SET(no).YSize SET(no).ZSize]); for rloop=1:length(rois) frames = SET(gui.magno).Roi(rois(rloop)).T(1); %handles.NO is the magnitude image stack slice = SET(gui.magno).Roi(rois(rloop)).Z(1); - for tloop = 1:length(frames) + roix = SET(gui.magno).Roi(rois(rloop)).X; + roiy = SET(gui.magno).Roi(rois(rloop)).Y; + % check if ROI is time resolved + numframes = length(frames); + nany = isnan(roiy(:)); + nanx = isnan(roix(:)); + if any(nanx) || any(nany) + % roi is not time resolved + % -> find time frame that has segmentation + [~,tf] = find(~isnan(roix)); + if ~isempty(tf) + tf = min(tf); + SET(gui.magno).Roi(rois(rloop)).X = repmat(roix(:,tf),[1,SET(no).TSize]); + SET(gui.magno).Roi(rois(rloop)).Y = repmat(roiy(:,tf),[1,SET(no).TSize]); + roiarea = SET(gui.magno).Roi(rois(rloop)).Area(1,tf); + SET(gui.magno).Roi(rois(rloop)).Area = repmat(roiarea,[1,SET(no).TSize]); + roistd = SET(gui.magno).Roi(rois(rloop)).StD(1,tf); + SET(gui.magno).Roi(rois(rloop)).StD = repmat(roistd,[1,SET(no).TSize]); + roimean = SET(gui.magno).Roi(rois(rloop)).Mean(1,tf); + SET(gui.magno).Roi(rois(rloop)).Mean = repmat(roimean,[1,SET(no).TSize]); + end + + end + for tloop = 1:numframes gui.logim(:,:,slice) = gui.logim(:,:,slice) | segment('createmask',... [SET(no).XSize SET(no).YSize],... - SET(gui.magno).Roi(rois(rloop)).Y(:,frames(tloop)),... - SET(gui.magno).Roi(rois(rloop)).X(:,frames(tloop))); - end; - end; - end; + SET(gui.magno).Roi(rois(rloop)).Y(:,frames(tloop)),... + SET(gui.magno).Roi(rois(rloop)).X(:,frames(tloop))); + end + end + end else @@ -599,11 +621,11 @@ function initvariables(no) [SET(no).XSize SET(no).YSize],... rois(rloop).Y(:,frames(tloop)),... rois(rloop).X(:,frames(tloop))); - end; - end; + end + end else excludeim = false([SET(no).XSize SET(no).YSize SET(no).ZSize]); - end; + end %Calculate the temporal standard deviation stdmap = std(SET(no).IM,0,3); @@ -651,14 +673,14 @@ function initvariables(no) %Remove zeros logim(stdmap==0) = false; gui.logim = logim; - end; + end %Recalculate %floweddycurrent_Callback('recalculate'); otherwise myfailed(dprintf('Method %s not implemented.',SET(no).Flow.PhaseCorrMethod)); myworkoff; return; -end; +end %--- Exclude non static tissue if ~gui.ignorerois @@ -668,8 +690,8 @@ function initvariables(no) for rloop=1:SET(gui.magno).RoiN if isequal(SET(gui.magno).Roi(rloop).Name,'Non-static tissue') rois = [rois rloop]; %#ok - end; - end; + end + end %Loop over ROI's and exclude them for rloop=1:length(rois) @@ -680,8 +702,8 @@ function initvariables(no) [SET(no).XSize SET(no).YSize],... SET(gui.magno).Roi(rois(rloop)).Y(:,frames(tloop)),... SET(gui.magno).Roi(rois(rloop)).X(:,frames(tloop))); - end; - end; + end + end %Later fix for multiple slices gui.logim = staticfix(gui.logim); @@ -693,8 +715,8 @@ function initvariables(no) for rloop=1:SET(gui.magno).RoiN if isequal(SET(gui.magno).Roi(rloop).Name,'Static tissue') rois = [rois rloop]; %#ok - end; - end; + end + end %Loop over ROI's and exclude them for rloop=1:length(rois) @@ -705,12 +727,12 @@ function initvariables(no) [SET(no).XSize SET(no).YSize],... SET(gui.magno).Roi(rois(rloop)).Y(:,frames(tloop)),... SET(gui.magno).Roi(rois(rloop)).X(:,frames(tloop))); - end; - end; + end + end %Later fix for multiple slices gui.logim = staticfix(gui.logim); -end; %do not do this if ignorerois are true +end %do not do this if ignorerois are true %Calculate number of static pixels, this is only for research purposes and %can later be deleted. @@ -721,7 +743,7 @@ function initvariables(no) numlower = sum(sum(gui.logim((half+1):end,:))); varargout{1} = numupper; varargout{2} = numlower; -end; +end myworkoff; @@ -748,7 +770,7 @@ function initvariables(no) numtimes = 10; if SET(gui.phaseno).Flow.PhaseCorrTimeResolved numtimes = 2; - end; + end if stop return; end @@ -766,7 +788,7 @@ function initvariables(no) end end -end; +end %Graphical update update; @@ -796,7 +818,7 @@ function initvariables(no) case 'ge' findstatic; %Check that this works return; -end; +end %Creat grid [x,y,z] = ndgrid(1:SET(no).XSize,1:SET(no).YSize,1:SET(no).ZSize); @@ -806,14 +828,14 @@ function initvariables(no) ind = find(gui.logim); else ind = find(gui.logim & (~gui.badfit)); %Remove badfit pixels -end; +end if length(ind)<50 myfailed('Too few points, aborting.'); stop = true; myworkoff; return; -end; +end %Cut away coordinates xi = x(:); yi=y(:); zi=z(:); @@ -828,13 +850,13 @@ function initvariables(no) A = [ones(size(xi)) xi yi zi]; else A = [ones(size(xi)) xi yi]; - end; + end case 2 if SET(no).ZSize>1 A = [ones(size(xi)) xi yi zi xi.*yi xi.*zi yi.*zi xi.^2 yi.^2 zi.^2]; else A = [ones(size(xi)) xi yi xi.*yi xi.^2 yi.^2]; - end; + end %case 3 % if SET(handles.no).ZSize>1 % myfailed('Not yet implemented.'); @@ -848,9 +870,9 @@ function initvariables(no) % A(:,5) = yi; %y % A(:,6) = A(:,5).*yi; %y^2 % A(:,7) = A(:,6).*yi; %y^3 - % end; + % end -end; +end %Build matrix switch order @@ -859,16 +881,16 @@ function initvariables(no) Abuild = [ones([size(x,1)*size(x,2)*size(x,3) 1]) x(:) y(:) z(:)]; else Abuild = [ones([size(x,1)*size(x,2) 1]) x(:) y(:)]; - end; + end case 2 if SET(no).ZSize>1 Abuild = [ones([size(x,1)*size(x,2)*size(x,3) 1]) x(:) y(:) z(:) x(:).*y(:) x(:).*z(:) y(:).*z(:) (x(:)).^2 (y(:)).^2 (z(:)).^2]; else Abuild = [ones([size(x,1)*size(x,2) 1]) x(:) y(:) x(:).*y(:) (x(:)).^2 (y(:)).^2]; - end; + end case 3 -end; +end %Check if timeresolved if SET(no).Flow.PhaseCorrTimeResolved @@ -876,7 +898,7 @@ function initvariables(no) handles.phasecorr = repmat(single(0),size(SET(no).IM)); else timeframes = 1; -end; +end %--- Loop over timeframes if timeresolved other wise loop just once. handles.maxvel = 0; @@ -889,7 +911,7 @@ function initvariables(no) phase = SET(no).IM(:,:,tloop,:)-0.5; else phase = mean(SET(no).IM(:,:,:,:),3)-0.5; - end; + end %Make as vector phase = phase(:); @@ -899,7 +921,7 @@ function initvariables(no) B = phase; tempstate = warning; - warning('off'); %#ok + warning('off'); c = A\double(B); %Solve! warning(tempstate); @@ -910,14 +932,14 @@ function initvariables(no) else gui.phasecorr = reshape(Abuild*c,[size(x,1) size(x,2) 1 SET(no).ZSize]); temp = gui.phasecorr; - end; + end temp(gui.logim) = 0; gui.maxvel = max(gui.maxvel,max(temp(:))); h = mywaitbarupdate(h); -end; %End of tloop +end %End of tloop mywaitbarclose(h); myworkoff; @@ -941,7 +963,7 @@ function initvariables(no) diffvel = vel-mean(gui.phasecorr,3)*2*SET(gui.phaseno).VENC; else diffvel = vel-gui.phasecorr*2*SET(gui.phaseno).VENC; -end; +end %Take only static pixels diffvel(~gui.logim) = 0; @@ -964,7 +986,7 @@ function initvariables(no) %--- warning messages if not enough (bad balanced support). [bwim] = bwlabel(mask,4); %4 connected regions varargout{1} = max(bwim(:)); -end; +end %---------------------- function clear_Callback %#ok @@ -999,7 +1021,7 @@ function initvariables(no) %--------------------- %Done button -global DATA +global DATA NO SET gui = DATA.GUI.EddyCurrent; @@ -1007,18 +1029,20 @@ function initvariables(no) plotonok = gui.plotonok; close(gui); -drawfunctions('drawimageno'); +drawfunctions('drawno',NO) if isopengui('flow.fig') reportflow('recalculate', magno); return; -end; +end if plotonok %Call plot function eddycheck = false; reportflow('init',magno,eddycheck); -end; +end +SET(magno).Flow.PhaseCorrAsk = false; %not ask this again for this stack +segment('updateflow'); %update flow values in main result panel %---------------------------- function smallcancel_Callback %#ok @@ -1034,28 +1058,32 @@ function initvariables(no) SET(magno).Flow.PhaseCorrAsk = false; close(gui); -drawfunctions('drawimageno'); +drawfunctions('drawno',magno); if isopengui('flow.fig') reportflow('recalculate', magno); return; -end; +end if plotonok %Call plot function eddycheck = false; reportflow('init',magno,eddycheck); -end; +end +SET(magno).Flow.PhaseCorrAsk = false; %not ask this again for this stack +segment('updateflow'); %update flow values in main result panel -%---------------- +%----------------------- function cancel_Callback %#ok %----------------------- %callback for cancel Eddy current compensation +global NO + if ~isopengui('flow.fig') - drawfunctions('drawimageno'); %update in main GUI -end; + drawfunctions('drawno',NO); %update in main GUI +end close_Callback; %---------------------- @@ -1103,7 +1131,7 @@ function initvariables(no) %Loop over objects and find number of pixels for loop = 1:maxclasses sizevec(loop) = sum(rowim==loop); - end; + end %Find suitable threshold of object sizes maxsize = max(sizevec); @@ -1114,12 +1142,12 @@ function initvariables(no) for loop = 1:maxclasses if sizevec(loop)>sizethreshold mergeim(im==loop) = true; - end; - end; + end + end %Store it fixim(:,:,slice) = mergeim; -end; +end %---------------------------- function smalladjust_Callback %#ok @@ -1152,20 +1180,23 @@ function initvariables(no) plotonok = gui.plotonok; %Close +no = gui.magno; close(gui); -drawfunctions('drawimageno'); +drawfunctions('drawno',no); %updated the flow interface if it is open if isopengui('flow.fig') reportflow('recalculate', magno); return; -end; +end if plotonok eddycheck = false; reportflow('init',magno,eddycheck); end +SET(no).Flow.PhaseCorrAsk = false; %not ask this again for this stack +segment('updateflow'); %update flow values in main result panel %-------------- function update @@ -1180,21 +1211,23 @@ function initvariables(no) if ~gui.biggui updatesmall; return; -end; +else + set(gui.fig,'Pointer', 'arrow') +end %Update timeresolved or not if SET(gui.phaseno).Flow.PhaseCorrTimeResolved set([gui.handles.timetext gui.handles.timeslider],'visible','on'); else set([gui.handles.timetext gui.handles.timeslider],'visible','off'); -end; +end %Extract maximum velocity gui.maxvel = max(abs(gui.phasecorr(:))); if isempty(gui.maxvel) gui.maxvel = 1; -end; +end %--- Show velocity if SET(gui.phaseno).Flow.PhaseCorrTimeResolved @@ -1204,11 +1237,11 @@ function initvariables(no) else temp = 2*SET(gui.phaseno).VENC*(mean(SET(gui.phaseno).IM(:,:,:,gui.slice),3)-0.5); temp(not(gui.logim(:,:,gui.slice))) = 0; %just show the static pixels -end; +end if ~isempty(gui.badfit) temp(gui.badfit(:,:,gui.slice)) = 0; %clear also badfit -end; +end imagesc(temp,'parent',gui.handles.phaseaxes); axis(gui.handles.phaseaxes,'image','off'); @@ -1218,7 +1251,7 @@ function initvariables(no) %Check if valid range if isequal(clim(1),0) clim = [-1 1]; -end; +end set(gui.handles.phaseaxes,'clim',clim); %colorbar('peer',handles.phaseaxes,'south'); @@ -1228,7 +1261,7 @@ function initvariables(no) imagesc(gui.phasecorr(:,:,gui.timeframe,gui.slice)*2*SET(gui.phaseno).VENC,'parent',gui.handles.phaseerroraxes); else imagesc(gui.phasecorr(:,:,1,gui.slice)*2*SET(gui.phaseno).VENC,'parent',gui.handles.phaseerroraxes); - end; + end axis(gui.handles.phaseerroraxes,'image','off'); %clim = get(handles.phaseaxes,'clim'); %clim = max(abs(clim)); @@ -1239,7 +1272,7 @@ function initvariables(no) imagesc(zeros(SET(gui.phaseno).XSize,SET(gui.phaseno).YSize),'parent',gui.handles.phaseerroraxes); colorbar('peer',gui.handles.phaseerroraxes,'East'); axis(gui.handles.phaseerroraxes,'image','off'); -end; +end %--- Show magnitude image magno = SET(gui.phaseno).Flow.MagnitudeNo; @@ -1249,7 +1282,7 @@ function initvariables(no) else %Not timeresolved tempim = calcfunctions('remapuint8',mean(SET(magno).IM(:,:,:,gui.slice),3),magno,graymap); -end; +end %Fix the red image tempr = tempim; @@ -1261,7 +1294,7 @@ function initvariables(no) tempg(gui.badfit(:,:,gui.slice)) = uint8(255); else tempg = tempim; -end; +end %Combine to an RGB image tempim = cat(3,tempr,tempg,tempim); @@ -1274,17 +1307,17 @@ function initvariables(no) temp = SET(gui.phaseno).Flow.PhaseCorr(:,:,gui.timeframe,gui.slice); else temp = SET(gui.phaseno).Flow.PhaseCorr(:,:,1,gui.slice); - end; + end else temp = zeros(SET(gui.phaseno).XSize,SET(gui.phaseno).YSize); -end; +end temp = 2*SET(gui.phaseno).VENC*temp; imagesc(temp,'parent',gui.handles.appliedphasecorraxes); axis(gui.handles.appliedphasecorraxes,'image','off'); colormap(gui.handles.appliedphasecorraxes,jet); if ~exist('clim','var') clim = [-gui.maxvel gui.maxvel]; -end; +end set(gui.handles.appliedphasecorraxes,'clim',clim); colorbar('peer',gui.handles.appliedphasecorraxes,'East'); @@ -1294,11 +1327,11 @@ function initvariables(no) for rloop=1:SET(gui.magno).RoiN if isequal(SET(gui.magno).Roi(rloop).Name,'Non-static tissue') nrois = [nrois rloop]; %#ok - end; + end if isequal(SET(gui.magno).Roi(rloop).Name,'Static tissue') srois = [srois rloop]; %#ok - end; -end; + end +end %Loop over ROI's and exclude them for rloop=1:length(nrois) @@ -1316,8 +1349,8 @@ function initvariables(no) SET(gui.magno).Roi(nrois(rloop)).X(:,1),'r-'); hold(gui.handles.previewaxes,'off'); - end; -end; + end +end for rloop=1:length(srois) slice = SET(gui.magno).Roi(srois(rloop)).Z(1); @@ -1333,8 +1366,8 @@ function initvariables(no) SET(gui.magno).Roi(srois(rloop)).Y(:,1),... SET(gui.magno).Roi(srois(rloop)).X(:,1),'b-'); hold(gui.handles.previewaxes,'off'); - end; -end; + end +end %Enable/disable relevant handles. h = [... @@ -1348,7 +1381,7 @@ function initvariables(no) set(h,'enable','off'); else set(h,'enable','on'); -end; +end %------------------- @@ -1365,7 +1398,7 @@ function initvariables(no) if isempty(gui.maxvel) gui.maxvel = 1; -end; +end %--- Show magnitude with overlayed velocity @@ -1377,7 +1410,7 @@ function initvariables(no) else vel = 2*SET(gui.phaseno).VENC*(mean(SET(gui.phaseno).IM(:,:,:,gui.slice),3)-0.5); vel(not(gui.logim(:,:,gui.slice))) = 0; %just show the static pixels -end; +end %Create magnitude image magno = SET(gui.phaseno).Flow.MagnitudeNo; @@ -1387,7 +1420,7 @@ function initvariables(no) else %Not timeresolved im = calcfunctions('remapuint8',mean(SET(magno).IM(:,:,:,gui.slice),3),magno,graymap); -end; +end %Create the RGB image rim = im; @@ -1427,7 +1460,7 @@ function initvariables(no) imagesc(gui.phasecorr(:,:,gui.timeframe,gui.slice)*2*SET(gui.phaseno).VENC,'parent',gui.handles.corraxes); else imagesc(gui.phasecorr(:,:,1,gui.slice)*2*SET(gui.phaseno).VENC,'parent',gui.handles.corraxes); - end; + end axis(gui.handles.corraxes,'image','off'); clim = 2*SET(gui.phaseno).VENC*[-gui.maxvel gui.maxvel]; set(gui.handles.corraxes,'clim',clim); @@ -1436,7 +1469,7 @@ function initvariables(no) imagesc(zeros(SET(gui.phaseno).XSize,SET(gui.phaseno).YSize),'parent',gui.handles.phaseerroraxes); colorbar('peer',gui.handles.corraxes,'East'); axis(gui.handles.corraxes,'image','off'); -end; +end %Find ROI's to graphically display nrois = []; @@ -1444,11 +1477,11 @@ function initvariables(no) for rloop=1:SET(gui.magno).RoiN if isequal(SET(gui.magno).Roi(rloop).Name,'Non-static tissue') nrois = [nrois rloop]; %#ok - end; + end if isequal(SET(gui.magno).Roi(rloop).Name,'Static tissue') srois = [srois rloop]; %#ok - end; -end; + end +end %Loop over ROI's and exclude them for rloop=1:length(nrois) @@ -1460,8 +1493,8 @@ function initvariables(no) SET(gui.magno).Roi(nrois(rloop)).X(:,1),'r-'); hold(gui.handles.magaxes,'off'); - end; -end; + end +end for rloop=1:length(srois) slice = SET(gui.magno).Roi(srois(rloop)).Z(1); @@ -1472,6 +1505,6 @@ function initvariables(no) SET(gui.magno).Roi(srois(rloop)).X(:,1),'b-'); hold(gui.handles.magaxes,'off'); - end; -end; + end +end diff --git a/source/flowunwrap.fig b/source/flowunwrap.fig index 86c7634..13c9542 100644 Binary files a/source/flowunwrap.fig and b/source/flowunwrap.fig differ diff --git a/source/flowunwrap.p b/source/flowunwrap.p index fe779da..ae52c6e 100644 Binary files a/source/flowunwrap.p and b/source/flowunwrap.p differ diff --git a/source/fourFlowExportGUI.m b/source/fourFlowExportGUI.m index 796bbd3..ce41f21 100644 --- a/source/fourFlowExportGUI.m +++ b/source/fourFlowExportGUI.m @@ -352,12 +352,12 @@ gui = DATA.GUI.FourFlowExport; %get from the global variable %Ask for filename -temp = pwd; +temp = DATA.SegmentFolder; if exist(DATA.Pref.exportpath,'dir') cd(DATA.Pref.exportpath); else mywarning('Export path does not exist, please check preferences.'); -end; +end pathname = myuigetdir('DATA.Pref.datapath', 'Choose empty directory for export'); choice = 2; diff --git a/source/fusion.p b/source/fusion.p index 7197e29..47c86d6 100644 Binary files a/source/fusion.p and b/source/fusion.p differ diff --git a/source/gapLayer.m b/source/gapLayer.m new file mode 100644 index 0000000..ad6e31a --- /dev/null +++ b/source/gapLayer.m @@ -0,0 +1,58 @@ +classdef gapLayer < nnet.layer.Layer + + properties + % (Optional) Layer properties. + + % Layer properties go here. + end + + properties (Learnable) + % (Optional) Layer learnable parameters. + + % Layer learnable parameters go here. + end + + methods + function layer = gapLayer(name) + % (Optional) Create a myLayer. + % This function must have the same name as the class. + + % Layer constructor function goes here. + layer.Name = name; + layer.Description = "Global average pooling layer"; + end + + function Z = predict(layer, X) + % Forward input data through the layer at prediction time and + % output the result. + % + % Inputs: + % layer - Layer to forward propagate through + % X1, ..., Xn - Input data + % Outputs: + % Z1, ..., Zm - Outputs of layer forward function + + % Layer forward function for prediction goes here. + Z = mean(mean(X,2),1); + end + + function dLdX = backward(layer, X, ~, dLdZ, ~) + % [dLdX, dLdAlpha] = backward(layer, X, ~, dLdZ, ~) + % backward propagates the derivative of the loss function + % through the layer. + % Inputs: + % layer - Layer to backward propagate through + % X - Input data + % dLdZ - Gradient propagated from the deeper layer + % Outputs: + % dLdX - Derivative of the loss with respect to the + % input data + % dLdAlpha - Derivative of the loss with respect to the + % learnable parameter Alpha + + dLdX = ones(size(X))/(size(X,1)*size(X,2)).*dLdZ; + + end + + end +end \ No newline at end of file diff --git a/source/gaussianintensityestimation.m b/source/gaussianintensityestimation.m index 2aca209..6ff9688 100644 --- a/source/gaussianintensityestimation.m +++ b/source/gaussianintensityestimation.m @@ -14,7 +14,7 @@ %sigma: standard deviation for the two classes (size 1*K) if nargin<3 - myfailed('Gaussianmixtureestimation requires at least 3 inputs'); + disp('Gaussianmixtureestimation requires at least 3 inputs'); end K=length(mu);%number of classes diff --git a/source/gaussianmixtureestimation.m b/source/gaussianmixtureestimation.m new file mode 100644 index 0000000..5a171c2 --- /dev/null +++ b/source/gaussianmixtureestimation.m @@ -0,0 +1,103 @@ +%-------------------------------------------------------------------------- +function [mu, sigma, alpha]=gaussianmixtureestimation(intensity, initialclassification, forceinitial, fixclass) +%-------------------------------------------------------------------------- + +%This function estimates a gaussian mixture model for the intensities using a modified version of the EM-algorithm. +%This version is used in t2wmarsegmentation. Autumn 2014 Jane discovered +%that this version of EM is not as correct as the one Felicia implemented +%in emalgorithm.m (or gaussianintensityestimation.m used by Jane in +%lvpeter.m). This version will however continue to be used by +%t2wmarsegmentation until cessfpmarsegmentation is implented and further evaluated +%in the data for T2-STIR. + + +%Input: +%intensity: vector of intenisties to be classified (size N*1) +%initialclassification: vector of original classification of intenisties to the +%classes size(N*1) +%forceinitial: vector of zeros and ones which forces a pixel to belong to +%the initialcalssification class (size N*1) +%fixclass: for a specific class mean and std can be fixed (size 1*K) +%Output: +%mu: mean intenisty for the two classes (size 1*K) +%sigma: standard deviation for the two classes (size 1*K) + +if nargin<2 + disp('Gaussianmixtureestimation requires at least 2 inputs'); +end + +K=max(initialclassification);%number of classes +N=length(initialclassification); + +if nargin<3 || isempty(forceinitial) + forceinitial=zeros(N,1); +end + +if nargin<4 || isempty(fixclass) + fixclass=zeros(1,K); +end + + +%error checking +for j=1:K + if isempty(find(initialclassification==j,1)) + disp(sprintf('All classes from 1 to %d must be represented in the classification vector',K)); + return; + end +end + +%intitialise mu, sigma and alpha +%alpha is the percent of intensities belogning to each class +mu=zeros(1,K); +sigma=zeros(1,K); +alpha=zeros(1,K); +for k=1:K + currentclass=(initialclassification==k); + currentintensity=intensity(currentclass); + mu(k)=mean(currentintensity); + sigma(k)=std(currentintensity); + alpha(k)=sum(currentclass)/length(intensity); +end + +%Set weights to force initialclassification +weights=ones(N,K); +for k=1:K + index = forceinitial & (initialclassification==k); + weights(index,:)=0; + weights(index,k)=1; +end + +%The EM algorithm +% The EM algorithm is used for classifying the intenisties to K classes +% In the Expectation step the probabilities of +% belonging to the K classes is calculated and the intensities are +% classified to the class for which it has the highest probability. +% In the Maximization step mean and standard deviation is calculated for +% the classes. In this modified version intensities can be forced to a spcific class and mean and standard +% deviation is updated for all classes but for those defined by fixclass +x=linspace(0,1,4096); +classprobability=zeros(N,K); +for t=1:50%should later be a while loop depending on an error calcualtion + %Expectation step + for k=1:K % all classes + tempgaussianpdf=alpha(k)*gaussianpdf(x,mu(k),sigma(k)); + classprobability(:,k)=weights(:,k).*fastremap(single(intensity),single(tempgaussianpdf)); + end + + [maxvalue,classification]=max(classprobability'); + + %Maximisation step + for k=1:K % all classes + if not(fixclass(k)) + currentclass=classification==k; + currentintensity=intensity(currentclass); + mu(k)=mean(currentintensity); + sigma(k)=std(currentintensity); + alpha(k)=sum(currentclass)/length(intensity); + end + end + + %calculate error (this is not yet done since no good error measurment + %have been found) + +end diff --git a/source/getimagedescription.p b/source/getimagedescription.p index b9f1af5..4ce4ad1 100644 Binary files a/source/getimagedescription.p and b/source/getimagedescription.p differ diff --git a/source/getkey.m b/source/getkey.m index 4eb479e..d990ef7 100644 --- a/source/getkey.m +++ b/source/getkey.m @@ -19,24 +19,28 @@ modifier = [modifier 'shift']; %#ok case 'alt' modifier = [modifier 'alt']; %#ok - end; + end if loop - end; - end; -end; + end + end +end key = evnt.Key; switch key case {'control','alt','shift'} key = ''; -end; +end if ~isempty(modifier) if ~isempty(key) - key = [modifier '-' key]; + ch = evnt.Character; + if ~isempty(key) && strcmp(ch,'+') + key = ch; + end + key = [modifier '-' key]; else key = modifier; - end; -end; \ No newline at end of file + end +end \ No newline at end of file diff --git a/source/getmodule.p b/source/getmodule.p index 628e2a6..bc6414c 100644 Binary files a/source/getmodule.p and b/source/getmodule.p differ diff --git a/source/getperfusionnbrs.m b/source/getperfusionnbrs.m new file mode 100644 index 0000000..5856fe0 --- /dev/null +++ b/source/getperfusionnbrs.m @@ -0,0 +1,98 @@ +function names = getperfusionnbrs(fieldkids,field) + global DATA + gui = DATA.GUI.Perfusion; + + upslopes = cell(16,1); + smoothupslopes = cell(16,1); + myored = cell(16,1); + myoblack = cell(16,1); + tangents = cell(16,1); + startline = get(gui.handles.([field 'startline']),'ydata'); + endline = get(gui.handles.([field 'endline']),'ydata'); + + bloodpool = get(gui.handles.([field 'bloodpool']), 'ydata'); + smoothbloodpool = get(gui.handles.([field 'smoothbloodpool']), 'ydata'); + + bloodred = get(gui.handles.([field 'bloodpoolred']), 'ydata'); + bloodblack = get(gui.handles.([field 'bloodpoolblack']), 'ydata'); + bptangent = get(gui.handles.([field 'bptangents']), 'ydata'); + + + for val = 6 + upslopes{val} = 0; + smoothupslopes{val} = get(gui.handles.([field 'smoothupslopes'])(val),'ydata'); + myored{val} = get(gui.handles.([field 'myored'])(val),'ydata'); + myoblack{val} = get(gui.handles.([field 'myoblack'])(val),'ydata'); + tangents{val} = get(gui.handles.([field 'tangents'])(val),'ydata'); + end + + names = cell(length(fieldkids),1); + for n = 1:length(fieldkids) + %Loop through all kids: + ykidstemp = get(fieldkids(n),'YData'); + foundupslopes = nnz(cellfun(@(x) isequal(x,ykidstemp),upslopes)); + + if foundupslopes==0 + foundsmoothupslopes = nnz(cellfun(@(x) isequal(x,ykidstemp),smoothupslopes)); + if foundsmoothupslopes==0 + foundmyored = nnz(cellfun(@(x) isequal(x,ykidstemp),myored)); + if foundmyored==0 + foundmyoblack = nnz(cellfun(@(x) isequal(x,ykidstemp),myoblack)); + if foundmyoblack==0 + foundtangents = nnz(cellfun(@(x) isequal(x,ykidstemp),tangents)); + if foundtangents==0 + foundstart = nnz(isequal(startline,ykidstemp)); + if foundstart==0 + foundend = nnz(isequal(endline,ykidstemp)); + if foundend==0 + foundblood = nnz(isequal(bloodpool,ykidstemp)); + if foundblood==0 + foundsmoothblood = nnz(isequal(smoothbloodpool,ykidstemp)); + if foundsmoothblood==0 + foundbloodred = nnz(isequal(bloodred,ykidstemp)); + if foundbloodred==0 + foundbloodblack = nnz(isequal(bloodblack,ykidstemp)); + if foundbloodblack==0 + foundbptangent = nnz(isequal(bptangent,ykidstemp)); + if foundbptangent==0 + names{n} = []; + else + names{n} = 'bptangent'; + end + else + names{n} = 'bloodblack'; + end + + else + names{n} = 'bloodred'; + end + + else + names{n} = 'smoothbloodpool'; + end + else + names{n} = 'bloodpool'; + end + else + names{n} = 'endline'; + end + else + names{n} = 'startline'; + end + else + names{n} = 'tangents'; + end + else + names{n} = 'myoblack'; + end + else + names{n} = 'myored'; + end + else + names{n} = 'smoothupslope'; + end + else + names{n} = 'upslope'; + end + end + end \ No newline at end of file diff --git a/source/getpreferencespath.m b/source/getpreferencespath.m index fc449ea..ad1d177 100644 --- a/source/getpreferencespath.m +++ b/source/getpreferencespath.m @@ -1,44 +1,63 @@ function pathname = getpreferencespath %Get path to preferences folders -global DATA -if isa(DATA,'maingui') - pathname = DATA.getpreferencespath; - return -end +% global DATA +persistent localprefpath +% if isa(DATA,'maingui') +% pathname = DATA.getpreferencespath; +% return +% end foldername = 'Segment'; - -if ispc - %Is Windows, check for better - temp = getenv('APPDATA'); - if not(isempty(temp)) - pathname = temp; - else - temp = getenv('USERPROFILE'); - if not(isempty(temp)) - pathname = temp; - else - temp = getenv('HOMEPATH'); +if isempty(localprefpath) + if ispc + % check if Siemens version +% s = commandlinehelper('getparameters'); +% if isfield(s,'LogFolder') && (~isempty(s.LogFolder)) +% % Siemens version +% pathname = s.LogFolder; +% else + %Is Windows, check for better + temp = getenv('APPDATA'); if not(isempty(temp)) pathname = temp; - end; - end; - end; - - %Check if subdirectory exists - if not(exist([temp filesep foldername],'dir')) - temppath = pwd; - cd(pathname); - disp(sprintf('Creating new folder %s%s%s',temp,filesep,foldername)); - suc = mkdir(foldername); - cd(temppath); - if not(suc) - myfailed(sprintf('Could not create %s%s%s',temp,filesep,foldername)); - end; - end; - - %Add Segment to the path - pathname= [pathname filesep foldername]; - -else - pathname = pwd; -end; %is pc \ No newline at end of file + else + temp = getenv('USERPROFILE'); + if not(isempty(temp)) + pathname = temp; + else + temp = getenv('HOMEPATH'); + if not(isempty(temp)) + pathname = temp; + end + end + end +% end + %Check if subdirectory exists + dirpath = [pathname filesep foldername]; + if not(exist(dirpath,'dir')) + try + fprintf('Creating new folder %s\n',dirpath); + suc = mkdir(dirpath); + if not(suc) + myfailed(dprintf('Could not create %s',dirpath)); + end + catch + myfailed(dprintf('Could not create %s',dirpath)); + end + % temppath = DATA.SegmentFolder; + % cd(pathname); + % disp(sprintf('Creating new folder %s%s%s',temp,filesep,foldername)); + % suc = mkdir(foldername); + % cd(temppath); + % if not(suc) + % myfailed(sprintf('Could not create %s%s%s',temp,filesep,foldername)); + % end + end + + %Add Segment to the path + localprefpath = dirpath; + + else + localprefpath = pwd; + end %is pc +end +pathname = localprefpath; \ No newline at end of file diff --git a/source/getpreview.p b/source/getpreview.p index 38f19e4..2f3db37 100644 Binary files a/source/getpreview.p and b/source/getpreview.p differ diff --git a/source/getrelpath.m b/source/getrelpath.m new file mode 100644 index 0000000..d87308a --- /dev/null +++ b/source/getrelpath.m @@ -0,0 +1,21 @@ +function relpath = getrelpath(basepath,path) +%Return relative path +%basepath is the basepath, and path is the pathname that should be +%shortened to a relative path + +%Einar Heiberg + +pos = length(basepath); +extractpath = path(1:pos); +if ~isequal(path(pos+1),filesep) + %Extra save attempt if last character is fileseparator. + if isequal(path(pos),filesep) + pos=pos-1; + else + error(sprintf('Expected file separator at this position. Basepath:%s Path:%s',basepath,path)); %#ok + end +end +relpath = path(pos+2:end); +if ~isequal(extractpath,basepath) + error(sprintf('Basepath and the begining of relpath should be the same. Should not occur. Basepath:%s Path:%s',basepath,path)); %#ok +end diff --git a/source/greyzonehist_alt.p b/source/greyzonehist_alt.p index 052c3fd..7a6d617 100644 Binary files a/source/greyzonehist_alt.p and b/source/greyzonehist_alt.p differ diff --git a/source/guessifdicom.m b/source/guessifdicom.m index ad00314..12b20b4 100644 --- a/source/guessifdicom.m +++ b/source/guessifdicom.m @@ -22,46 +22,46 @@ if isequal(ext,'.dcm') || isequal(ext,'.segdicom') || isequal(ext,'.dicom') isdicom = true; %It is a .dcm file return; - end; + end %Starts with Modality and contains a lot of . if length(filename)>4 if ... - ~isempty(strfind(filename,'MR.')) || ... - ~isempty(strfind(filename,'MRe.')) || ... - ~isempty(strfind(filename,'SC.')) || ... - ~isempty(strfind(filename,'CT.')) || ... - ~isempty(strfind(filename,'CTe.')) || ... - ~isempty(strfind(filename,'PT.')) || ... - ~isempty(strfind(filename,'NM.')) || ... - ~isempty(strfind(filename,'OT.')) || ... - ~isempty(strfind(filename,'XR.')) + contains(filename,'MR.') || ... + contains(filename,'MRe.') || ... + contains(filename,'SC.') || ... + contains(filename,'CT.') || ... + contains(filename,'CTe.') || ... + contains(filename,'PT.') || ... + contains(filename,'NM.') || ... + contains(filename,'OT.') || ... + contains(filename,'XR.') if sum(filename=='.')>=6 isdicom = true; return; - end; - end; - if ~isempty(strfind(filename,'PSg.')) || ... - ~isempty(strfind(filename,'REG.')) || ... - ~isempty(strfind(filename,'SRc.')) || ... - ~isempty(strfind(filename,'SRd.')) || ... - ~isempty(strfind(filename,'SRe.')) || ... - ~isempty(strfind(filename,'SRt.')) + end + end + if contains(filename,'PSg.') || ... + contains(filename,'REG.') || ... + contains(filename,'SRc.') || ... + contains(filename,'SRd.') || ... + contains(filename,'SRe.') || ... + contains(filename,'SRt.') isdicom = false; return; end if isequal(filename(1:3),'im-') isdicom = true; - end; - end; + end + end %Files with only numbers and no extension if isequal(filename,removechars(filename)) && isempty(ext) isdicom = true; return; - end; + end % It's not a dicom file if the file ends with '.???' if regexp(rawfilename, '\....$') @@ -69,7 +69,7 @@ isdicom = false; return; end - end; + end if isequal(lower(ext),'.cache') isdicom = false; return; @@ -79,8 +79,8 @@ % return; % end - if ~isempty(strfind(filename,'VERSION')) - isdicom =false; + if contains(filename,'VERSION') + isdicom = false; return; end @@ -88,49 +88,53 @@ isequal(filename,'thumbs.cache') || ... isequal(filename,'folders.cache') || ... isequal(filename,'dicom.cache')) - - - - try - temp=dicominfo(rawfilename); - if isfield(temp,'ImagingFrequency') %Fixed for Toshiba/Canon 3T MRI sending images directly from MRISystem - if (round(temp.ImagingFrequency) == 123) && ( strcmpi(temp.Manufacturer,'toshiba')|| strcmpi(temp.Manufacturer,'canon')) - if strcmp(temp.ImageType,'ORIGINAL\PRIMARY\OTHER')&&strcmp(temp.SequenceName,'PSMRA') - isdicom=true; - elseif strcmp(temp.ImageType,'ORIGINAL\PRIMARY\OTHER') || strcmp(temp.ImageType,'DERIVED\SECONDARY\SHIMMING') - isdicom=false; + + try + segdicomtags.readfiles({rawfilename}); + isdicom = true; + return; + catch + try + temp = dicominfo(rawfilename); + if isfield(temp,'ImagingFrequency') %Fixed for Toshiba/Canon 3T MRI sending images directly from MRISystem + if (round(temp.ImagingFrequency) == 123) && ( strcmpi(temp.Manufacturer,'toshiba')|| strcmpi(temp.Manufacturer,'canon')) + if strcmp(temp.ImageType,'ORIGINAL\PRIMARY\OTHER')&&strcmp(temp.SequenceName,'PSMRA') + isdicom = true; + elseif strcmp(temp.ImageType,'ORIGINAL\PRIMARY\OTHER') || strcmp(temp.ImageType,'DERIVED\SECONDARY\SHIMMING') + isdicom = false; + else + isdicom = true; + end else - isdicom=true; + isdicom = true; %For all other MR end else - isdicom=true; %For all other MR + isdicom = true; %In the case that it is not MR but CT end - else - isdicom=true; %In the case that it is not MR but CT + + return; + catch + %mywarning('The File is not DICOM'); + isdicom = false; + return; end - - return; - catch - %mywarning('The File is not DICOM'); - isdicom =false; - return; + % temp=dicominfo(rawfilename); + % if isfield(dicominfo(rawfilename),'Format') + % if strcmp(temp.Format,'DICOM') + % isdicom = true; + % return; + % end + % end end -% temp=dicominfo(rawfilename); -% if isfield(dicominfo(rawfilename),'Format') -% if strcmp(temp.Format,'DICOM') -% isdicom = true; -% return; -% end -% end - end - - % if we're still not sure try and load the file - %disp(rawfilename); - + + % if we're still not sure try and load the file + %disp(rawfilename); + end try segdicomtags.readfiles({rawfilename}); isdicom = true; + return catch e if not(strcmp(e.identifier, 'SEGMENT:ERROR')) rethrow(e); @@ -142,7 +146,7 @@ ext = lower(ext); if isequal(ext,'.dcm') || isequal(ext,'.ima') isdicom = true; %It is a .dcm file - end; + end case 3 if not(... diff --git a/source/hasloop.mexw32 b/source/hasloop.mexw32 deleted file mode 100644 index 8639852..0000000 Binary files a/source/hasloop.mexw32 and /dev/null differ diff --git a/source/helpfigure.fig b/source/helpfigure.fig new file mode 100644 index 0000000..993adb8 Binary files /dev/null and b/source/helpfigure.fig differ diff --git a/source/ijg12.dll b/source/ijg12.dll new file mode 100644 index 0000000..8eace6e Binary files /dev/null and b/source/ijg12.dll differ diff --git a/source/ijg16.dll b/source/ijg16.dll new file mode 100644 index 0000000..405e2af Binary files /dev/null and b/source/ijg16.dll differ diff --git a/source/ijg8.dll b/source/ijg8.dll new file mode 100644 index 0000000..9796220 Binary files /dev/null and b/source/ijg8.dll differ diff --git a/source/imagedescription.p b/source/imagedescription.p index 6bc2257..73bc669 100644 Binary files a/source/imagedescription.p and b/source/imagedescription.p differ diff --git a/source/imagedescription.txt b/source/imagedescription.txt index 9e0a3bd..49e1d8b 100644 --- a/source/imagedescription.txt +++ b/source/imagedescription.txt @@ -26,7 +26,6 @@ Strain from tagging,,TAG,,, Strain from tagging,,SPAMM,,, Strain from tagging,,grid,,, T1BB,,T1,,, -T1BB,,BB,,, T1BB FS,,T1W1 FS BB,,, T1 map,,MOLLI,,, T1 map Pre,,MOLLI pre-Gd,,, @@ -38,6 +37,7 @@ T1 map Post,,T1Map_Short,,, TI prep,, TI prep,,, T2 map,,T2map,,, T2BB,,T2WI,,, +T2BB,,T2w/STIR/BB,,, T2Stir,,stir,,, T2* map,,star,,, TripleIR,,TRIPLE IR,,, diff --git a/source/imageinfo.fig b/source/imageinfo.fig index 6f25566..bad9f2c 100644 Binary files a/source/imageinfo.fig and b/source/imageinfo.fig differ diff --git a/source/importantmessage.fig b/source/importantmessage.fig index b3ddd84..4da2f02 100644 Binary files a/source/importantmessage.fig and b/source/importantmessage.fig differ diff --git a/source/importantmessage.p b/source/importantmessage.p index 1151ec0..3fd4ddc 100644 Binary files a/source/importantmessage.p and b/source/importantmessage.p differ diff --git a/source/infarctbyewa.fig b/source/infarctbyewa.fig index 0c8f0cf..fb3c5c5 100644 Binary files a/source/infarctbyewa.fig and b/source/infarctbyewa.fig differ diff --git a/source/infarctbyewa.p b/source/infarctbyewa.p index 9625d6d..47af5b7 100644 Binary files a/source/infarctbyewa.p and b/source/infarctbyewa.p differ diff --git a/source/inputstruct.m b/source/inputstruct.m index e21d72b..871f2db 100644 --- a/source/inputstruct.m +++ b/source/inputstruct.m @@ -1,9 +1,10 @@ -function [res,varargout] = inputstruct(s,tit) +function [res,varargout] = inputstruct(s,tit,text) %INPUTSTRUCT creates a popup input dialog box from a struct % % INPUTSTRUCT(struct_var,title) % -% Input is a struct with exploraty names, and a title for the dialogbox +% Input is a struct with exploraty names, a title for the dialogbox +% and a descriptive text % Output is the modified struct, and optional an ok variable. % % Example @@ -28,30 +29,28 @@ % - double(s) % - chars or string arrays % - logicals -% -% See also INPUTDLG, COPYFIELDS. %Einar Heiberg 2003-12-04 if nargin==0 error('Expected at least one input argument.'); -end; +end if nargin==1 tit = inputname(1); -end; +end -if nargin>2 - error('Expected no more than two input arguments.'); -end; +if nargin>3 + error('Expected no more than three input arguments.'); +end if length(s)>1 error('Expected a struct, not an array of structs.'); -end; +end if nargout>2 error('Expected only two output arguments.'); -end; +end %Get the fieldsnames fields = fieldnames(s); @@ -59,20 +58,23 @@ if numfields<1 error('Input is not a struct.'); -end; +end %Set default answer as failed if nargout==2 varargout = cell(1,1); varargout{1} = false; -end; +end %Create variables for dialogbox -prompt = cell(size(fields)); def = cell(size(fields)); lineno = zeros(numfields,1); for loop=1:numfields - prompt{loop} = [fields{loop} ':']; + if nargin > 2 && length(text) == length(fields) %input descriptive text for each variable + prompt{loop} = [text{loop} ':']; + else + prompt{loop} = [fields{loop} ':']; + end switch class(getfield(s,fields{loop})) case 'logical' temp = getfield(s,fields{loop}); @@ -80,24 +82,24 @@ def{loop} = 'true'; else def{loop} = 'false'; - end; + end otherwise def{loop} = num2str(getfield(s,fields{loop})); - end; + end lineno(loop) = max(size(def{loop},1),1); -end; +end %Bring up the dialogbox keystroke = popfrombuffer('KeyStroke'); if isempty(keystroke) - answ = inputdlg(prompt,tit,lineno,def); + answ = myinputdlg(prompt,tit,lineno,def); else if isequal(keystroke,'ok') answ = def; else error('Expected ''ok'' as keystroke.'); - end; -end; + end +end if isempty(answ) %User pressed cancel, return the same. @@ -121,7 +123,7 @@ myfailed(dprintf('Could not convert %s to number.',fields{loop})); res = setfield(res,fields{loop},getfield(s,fields{loop})); ok = false; - end; + end case 'logical' %Convert to number switch lower(answ{loop}) @@ -134,10 +136,10 @@ myfailed(dprintf('Could not convert %s to logical.',fields{loop})); ok = false; res = setfield(res,fields{loop},getfield(s,fields{loop})); - end; + end otherwise error(sprintf('Input type %s not supported.',class(getfield(s,fields{loop})))); - end; - end; -end; -varargout{1} = ok; \ No newline at end of file + end + end +end +varargout{1} = ok; diff --git a/source/isapproxequal.m b/source/isapproxequal.m new file mode 100644 index 0000000..60d53ca --- /dev/null +++ b/source/isapproxequal.m @@ -0,0 +1,30 @@ +function z = isapproxequal(a,b,tol) +%ISAPPROXEQUAL Same as isequal, but with tolerance for numeric arrays. + +%Einar Heiberg + +if nargin<3 + tol = 1e-4; +end +if strcmp(mexext,'mexw32') + if nargin >= 3 + tol = max(tol,b*0.02); + else + tol = b*0.02; + end + tol = abs(tol); +end +if ~isnumeric(a) + z = isequal(a,b); + return; +end +if isequal(size(a),size(b)) + if all(abs((a(:)-b(:)))<=tol(:)) + z = true; + else + z = false; + end +else + z = false; +end +end \ No newline at end of file diff --git a/source/issimplepoly.mexw32 b/source/issimplepoly.mexw32 deleted file mode 100644 index e92b510..0000000 Binary files a/source/issimplepoly.mexw32 and /dev/null differ diff --git a/source/iswindowsadmin.m b/source/iswindowsadmin.m new file mode 100644 index 0000000..00b5a56 --- /dev/null +++ b/source/iswindowsadmin.m @@ -0,0 +1,5 @@ +function out = iswindowsadmin() +%ISWINDOWSADMIN True if this user is in admin role. +wi = System.Security.Principal.WindowsIdentity.GetCurrent(); +wp = System.Security.Principal.WindowsPrincipal(wi); +out = wp.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator); \ No newline at end of file diff --git a/source/killhandles.m b/source/killhandles.m index dcdf526..0f6eb15 100644 --- a/source/killhandles.m +++ b/source/killhandles.m @@ -14,16 +14,10 @@ subhandles = guihandles(subfig); fnames = fieldnames(subhandles); - if strcmp(subfigfile,'segment.fig'); - icons1 = maintoolbaricons; - icons2 = segment('initviewtoolbar'); - fnames = [fnames; icons1; icons2]; - end - addhandles = addedhandles(subfigfile); fnames = [fnames; addhandles]; - for loop = 1:length(fnames); + for loop = 1:length(fnames) field = fnames{loop}; if ~isfield(mainhandles,field) mainhandles.(field) = []; @@ -33,52 +27,6 @@ delete(subfig); end -%-------------------------------- -function icons = maintoolbaricons -%-------------------------------- -icons = {'maintoolbar' - 'fileopenicon' - 'filesaveicon' - 'databaseicon' - 'databaseaddicon' - 'pacsicon' - 'pacsaddicon' - 'importfromcdicon' - 'view1panelicon' - 'view2panelicon' - 'view2x1panelicon' - 'view3panelicon' - 'view1x3panelicon' - 'view4panelicon' - 'view6panelicon' - 'view9panelicon' - 'view12panelicon' - 'view16panelicon' - 'panelallicon' - 'saveviewicon' - 'hidepinsicon' - 'hideothercontouricon' - 'hideinterpicon' - 'hidelvicon' - 'hidervicon' - 'hidescaricon' - 'hidemaricon' - 'hideroiicon' - 'hidemeasuresicon' - 'hidepointsicon' - 'hideplusicon' - 'hideintersectionsicon' - 'hidetexticon' - 'hidepapicon' - 'hidesectorgridicon' - 'hideoverlayicon' - 'abouticon' - 'viewpixelyicon' - 'orthoviewicon' - 'mipicon' - 'colorbaricon' - 'autocontrastallicon'}; - %--------------------------------------------- function newhandles = addedhandles(subfigfile) %--------------------------------------------- diff --git a/source/label.p b/source/label.p index 3ff82f4..ad13199 100644 Binary files a/source/label.p and b/source/label.p differ diff --git a/source/labelunknown.m b/source/labelunknown.m deleted file mode 100644 index fca5980..0000000 --- a/source/labelunknown.m +++ /dev/null @@ -1,15 +0,0 @@ -function newobjectlabel=labelunknown(objectlabel,unknownindex) - -xsize=size(objectlabel,1); -ysize=size(objectlabel,2); -zsize=size(objectlabel,3); - -[x,y,z]=ind2sub([xsize ysize zsize],unknownindex); -valid=(x>1 &x1 &y1 &z0 && isempty(setstruct(no).RoiCurrent) + setstruct(no).RoiCurrent = 1; + end end -% %Roi Area field check -% for no = 1:length(setstruct) -% if not(isfield(setstruct(no).Roi,'Area')) -% if setstruct(no).RoiN > 0 -% for roinum = 1:setstruct(no).RoiN -% setstruct(no).Roi(roinum).Area = 0; -% setstruct(no).Roi(roinum).Mean = 0; -% setstruct(no).Roi(roinum).StD = 0; -% end -% else -% setstruct(no).Roi.Area = []; -% setstruct(no).Roi.Mean = []; -% setstruct(no).Roi.StD = []; -% end -% end -% end %Respiratory if not(isfield(setstruct,'Respiratory')) for no = 1:length(setstruct) setstruct(no).Respiratory = []; - end; -end; + end +end +%New General Pen +if not(isfield(setstruct,'GeneralPenX')) + for no = 1:length(setstruct) + setstruct(no).GeneralPenX = []; + setstruct(no).GeneralPenY = []; + end +end + +%New General Pen Interp +if not(isfield(setstruct,'GeneralPenInterpX')) + for no = 1:length(setstruct) + setstruct(no).GeneralPenInterpX = []; + setstruct(no).GeneralPenInterpY = []; + end +end %Start analysis field check if not(isfield(setstruct,'StartAnalysis')) for no = 1:length(setstruct) setstruct(no).StartAnalysis = 1; setstruct(no).EndAnalysis = setstruct(no).TSize; - end; -end; + end +end for no = 1:length(setstruct) if isempty(setstruct(no).StartAnalysis) setstruct(no).StartAnalysis = 1; setstruct(no).EndAnalysis = setstruct(no).TSize; - end; -end; + end +end %Resolution field check if not(isfield(setstruct,'ResolutionX')) for no = 1:length(setstruct) setstruct(no).ResolutionX = setstruct(no).Resolution; setstruct(no).ResolutionY = setstruct(no).Resolution; - end; -end; + end +end for no = 1:length(setstruct) if isempty(setstruct(no).ResolutionX) && isfield(setstruct(no),'Resolution') setstruct(no).ResolutionX = setstruct(no).Resolution; setstruct(no).ResolutionY = setstruct(no).Resolution; - end; -end; + end +end %Endocenter field check if not(isfield(setstruct,'EndoCenter')) for no = 1:length(setstruct) setstruct(no).EndoCenter = DATA.Pref.EndoCenter; - end; -end; + end +end for no = 1:length(setstruct) if isempty(setstruct(no).EndoCenter) setstruct(no).EndoCenter = DATA.Pref.EndoCenter; - end; -end; + end +end if not(isfield(setstruct,'NormalZoomState')) for no = 1:length(setstruct) setstruct(no).NormalZoomState = []; - end; -end; + end +end if not(isfield(setstruct,'MontageZoomState')) for no = 1:length(setstruct) setstruct(no).MontageZoomState = []; - end; -end; + end +end if not(isfield(setstruct,'MontageRowZoomState')) for no = 1:length(setstruct) setstruct(no).MontageRowZoomState = []; - end; -end; + end +end if not(isfield(setstruct,'MontageFitZoomState')) for no = 1:length(setstruct) setstruct(no).MontageFitZoomState = []; - end; -end; + end +end if not(isfield(setstruct,'Rotated')) for no = 1:length(setstruct) setstruct(no).Rotated = false; - end; -end; + end +end if not(isfield(setstruct,'Flow')) for no = 1:length(setstruct) setstruct(no).Flow = []; - end; -end; + end +end for no = 1:length(setstruct) if not(isempty(setstruct(no).Flow)) @@ -216,31 +273,75 @@ end end end +% check if number of ROIs corresponds to the length of ROI stuct +for no = 1:length(setstruct) + numrois = length(setstruct(no).Roi); + if setstruct(no).RoiN ~= 0 && setstruct(no).RoiN ~= numrois + for roiloop = 1:numrois + % check + if isempty(setstruct(no).Roi(roiloop).X) || isempty(setstruct(no).Roi(roiloop).Y) + setstruct(no).Roi(roiloop) = []; + end + end + end +end + +%This addition Writes the flow area if it exists over the area parameter +for no = 1:length(setstruct) + if not(isempty(setstruct(no).Flow)) + if isfield(setstruct(no).Flow,'Result') + for roiloop = 1:length(setstruct(no).Flow.Result) + if roiloop <= setstruct(no).RoiN + if isfield(setstruct(no).Flow.Result(roiloop),'area') + lengthflowresult = nnz(setstruct(no).Flow.Result(roiloop).area); + if lengthflowresult ~= setstruct(no).TSize + % correct results if their length without zero values is not the same as TSize + numtimeframes = setstruct(no).TSize; + setstruct(no).Flow.Result(roiloop).area = rebuildflowresults(setstruct(no).Flow.Result(roiloop).area,numtimeframes); + setstruct(no).Flow.Result(roiloop).velmean = rebuildflowresults(setstruct(no).Flow.Result(roiloop).velmean,numtimeframes); + setstruct(no).Flow.Result(roiloop).velstd = rebuildflowresults(setstruct(no).Flow.Result(roiloop).velstd,numtimeframes); + setstruct(no).Flow.Result(roiloop).velmax = rebuildflowresults(setstruct(no).Flow.Result(roiloop).velmax,numtimeframes); + setstruct(no).Flow.Result(roiloop).velmin = rebuildflowresults(setstruct(no).Flow.Result(roiloop).velmin,numtimeframes); + setstruct(no).Flow.Result(roiloop).kenergy = rebuildflowresults(setstruct(no).Flow.Result(roiloop).kenergy,numtimeframes); + setstruct(no).Flow.Result(roiloop).netflow = rebuildflowresults(setstruct(no).Flow.Result(roiloop).netflow,numtimeframes); + setstruct(no).Flow.Result(roiloop).posflow = rebuildflowresults(setstruct(no).Flow.Result(roiloop).posflow,numtimeframes); + setstruct(no).Flow.Result(roiloop).negflow = rebuildflowresults(setstruct(no).Flow.Result(roiloop).negflow,numtimeframes); + end + setstruct(no).Roi(roiloop).Area = setstruct(no).Flow.Result(roiloop).area; + end + else + % there is no corresponding ROI for the result -> delete result + setstruct(no).Flow.Result(roiloop) = []; + end + end + end + end +end if not(isfield(setstruct,'VENC')) for no = 1:length(setstruct) setstruct(no).VENC = 0; - end; -end; + end +end if not(isfield(setstruct,'OrigFileName')) for no = 1:length(setstruct) setstruct(no).OrigFileName = setstruct(no).FileName; - end; -end; + end +end % JU Measure now time dependent if not(isfield(setstruct,'Measure')) for no = 1:length(setstruct) setstruct(no).Measure = []; - end; + end else for no = 1:length(setstruct) if (isfield(setstruct(no).Measure,'X')&¬(isfield(setstruct(no).Measure,'T'))) for loop=1:length(setstruct(no).Measure) setstruct(no).Measure(loop).T = NaN; - end; - end; + end + end if isfield(setstruct(no).Measure,'Z') for loop=1:length(setstruct(no).Measure) if numel(setstruct(no).Measure(loop).Z) == 1 @@ -248,154 +349,26 @@ end end end - end; -end; + end +end if not(isfield(setstruct,'Report')) for no = 1:length(setstruct) setstruct(no).Report = []; - end; -end; + end +end for no = 1:length(setstruct) if ~isfield(setstruct(no),'RV') setstruct(no).RV = []; -% setstruct(no).RV.centerbasal=[setstruct(no).CenterX,setstruct(no).CenterY]; -% setstruct(no).RV.centerapical=[setstruct(no).CenterX,setstruct(no).CenterY]; -% setstruct(no).RV.slicebasal=1; -% setstruct(no).RV.sliceapical=setstruct(no).ZSize; - end; + end end if not(isfield(setstruct,'LevelSet')) for no = 1:length(setstruct) setstruct(no).LevelSet = []; - end; + end end -% if not(isfield(setstruct,'LevelSet')) -% for no = 1:length(setstruct) -% setstruct(no).LevelSet = []; -% end; -% else -% for no = 1:length(setstruct) -% if not(isempty(setstruct(no).LevelSet)) -% levelset('levelsetdefault',no);%does not change .BW or .Man subfield .Object -% for fdloop = {'Ind', 'Names', 'Int'} -% fname = fdloop{:}; -% obname = ['Object' fname]; -% if isfield(setstruct(no).LevelSet,obname) -% setstruct(no).LevelSet.Object.(fname)=setstruct(no).LevelSet.(obname); -% setstruct(no).LevelSet=rmfield(setstruct(no).LevelSet,obname); -% end -% end -% if ~isfield(setstruct(no).LevelSet.Object,'Int') -% setstruct(no).LevelSet.Object.Int = cell(1,length(setstruct(no).LevelSet.Object.Ind)); -% for loop=1:length(setstruct(no).LevelSet.Object.Int) -% setstruct(no).LevelSet.Object.Int{loop} = repmat(uint8(255),... -% size(setstruct(no).LevelSet.Object.Ind{loop})); -% end -% end -% -% %subfield .Speed -% fnames_old = {'offset', 'mappingmode', 'slope', 'fromseed', ... -% 'ObjInt', 'minInt', 'maxInt', 'histx', 'intensitymap'}; -% fnames_new = {'OffSet', 'MappingMode', 'Slope', 'UseFromSeed', ... -% 'IntensityFromSeed', 'MinIntensity', 'MaxIntensity', 'Histx', ... -% 'IntensityMap'}; -% for floop = 1:numel(fnames_old) -% f_old = fnames_old{floop}; -% f_new = fnames_new{floop}; -% if isfield(setstruct(no).LevelSet,f_old) -% setstruct(no).LevelSet.Speed.(f_new) = setstruct(no).LevelSet.(f_old); -% setstruct(no).LevelSet = rmfield(setstruct(no).LevelSet,f_old); -% end -% end -% -% %subfield .Segmentation -% fnames_new = {'Alpha', 'Beta', 'Radius', 'SmoothRadius'}; -% fnames_old = lower(fnames_new); -% for floop = 1:numel(fnames_old) -% f_old = fnames_old{floop}; -% f_new = fnames_new{floop}; -% if isfield(setstruct(no).LevelSet,f_old) -% setstruct(no).LevelSet.Segmentation.(f_new) = setstruct(no).LevelSet.(f_old); -% setstruct(no).LevelSet = rmfield(setstruct(no).LevelSet,f_old); -% end -% end -% -% %subfield .View -% fnames1 = {'MIP', 'Interaction', 'Selection', 'Outline'}; -% fnames2 = {'RZoomState', 'GZoomState', 'BZoomState', ... -% 'CurrentTool', 'ResolutionT', 'Zoom'}; -% fnames3 = {'Pointer', 'RSlice', 'BSlice', 'GSlice', 'TSlice', ... -% 'ZSlice'}; -% fnames_new = [fnames1 fnames2 fnames3]; -% fnames_old = [cellfun(@(x)horzcat('View',x),fnames1,... -% 'UniformOutput',false) fnames2 lower(fnames3)]; -% -% for floop = 1:numel(fnames_old) -% f_old = fnames_old{floop}; -% f_new = fnames_new{floop}; -% if isfield(setstruct(no).LevelSet,f_old) -% setstruct(no).LevelSet.View.(f_new) = setstruct(no).LevelSet.(f_old); -% setstruct(no).LevelSet = rmfield(setstruct(no).LevelSet,f_old); -% end -% end -% -% %subfield .Pen -% fnames_new = {'Radius', 'Color', 'TSize', ... -% 'ZSize', 'Index', 'X', 'Y', 'T', 'Z', 'Value'}; -% fnames_old = {'penradius', 'pencolor', 'pentsize', ... -% 'penzsize', 'pen', 'penX', 'penY', 'penT', 'penZ', 'penvalue'}; -% for floop = 1:numel(fnames_old) -% f_old = fnames_old{floop}; -% f_new = fnames_new{floop}; -% if isfield(setstruct(no).LevelSet,f_old) -% setstruct(no).LevelSet.Pen.(f_new) = setstruct(no).LevelSet.(f_old); -% setstruct(no).LevelSet = rmfield(setstruct(no).LevelSet,f_old); -% end -% end -% if isfield(setstruct(no).LevelSet,'penpsize'); -% setstruct(no).LevelSet.Pen.XSize=setstruct(no).LevelSet.penpsize; -% setstruct(no).LevelSet.Pen.YSize=setstruct(no).LevelSet.penpsize; -% end -% -% %subfield .Prototype -% fnames_new = {'ChosenPrototype', 'ViewStartIndex', ... -% 'UsePrototypeParameters', 'UseCurvatureMap', 'LandmarkChanged', ... -% 'Lambda'}; -% fnames_old = {'chosenPrototype', 'ViewStartindex', ... -% 'UsePrototypeParameters', 'UseCurvature', 'LMchanged', 'lambda'}; -% for floop = 1:numel(fnames_old) -% f_old = fnames_old{floop}; -% f_new = fnames_new{floop}; -% if isfield(setstruct(no).LevelSet,f_old) -% setstruct(no).LevelSet.Prototype.(f_new) = setstruct(no).LevelSet.(f_old); -% setstruct(no).LevelSet = rmfield(setstruct(no).LevelSet,f_old); -% end -% end -% -% %subfield RegionGrowing -% if isfield(setstruct(no).LevelSet,'expansionfactor'); -% setstruct(no).LevelSet.Prototype.ExpansionFactor=setstruct(no).LevelSet.expansionfactor; -% setstruct(no).LevelSet=rmfield(setstruct(no).LevelSet,'expansionfactor'); -% end -% if isfield(setstruct(no).LevelSet,'iterationexponent'); -% setstruct(no).LevelSet.Prototype.IterationExponent=setstruct(no).LevelSet.iterationexponent; -% setstruct(no).LevelSet=rmfield(setstruct(no).LevelSet,'iterationexponent'); -% end -% -% %remove other obsolete fields -% fnames_old = {'ViewMagIm', 'ViewIm', 'penind', 'pentimes'}; -% for floop = 1:numel(fnames_old) -% f_old = fnames_old{floop}; -% if isfield(setstruct(no).LevelSet,f_old); -% setstruct(no).LevelSet=rmfield(setstruct(no).LevelSet,f_old); -% end -% end -% end -% end -% end %Orgsize field check if not(isfield(setstruct,'OrgXSize')) @@ -404,8 +377,8 @@ setstruct(no).OrgYSize = 256; setstruct(no).OrgTSize = setstruct(no).TSize; setstruct(no).OrgZSize = setstruct(no).ZSize; - end; -end; + end +end %Orgresolution field check if not(isfield(setstruct,'OrgRes')) @@ -413,16 +386,16 @@ setstruct(no).OrgRes = [setstruct(no).ResolutionX,... setstruct(no).ResolutionY,setstruct(no).SliceThickness + ... setstruct(no).SliceGap,setstruct(no).TIncr]; - end; -end; + end +end for no = 1:length(setstruct) if isempty(setstruct(no).OrgRes) setstruct(no).OrgRes = [setstruct(no).ResolutionX,... setstruct(no).ResolutionY,setstruct(no).SliceThickness + ... setstruct(no).SliceGap,setstruct(no).TIncr]; - end; -end; + end +end for no = 1:length(setstruct) if isempty(setstruct(no).OrgXSize) @@ -430,21 +403,21 @@ setstruct(no).OrgYSize = 256; setstruct(no).OrgTSize = setstruct(no).TSize; setstruct(no).OrgZSize = setstruct(no).ZSize; - end; -end; + end +end if not(isfield(setstruct,'GEVENCSCALE')) for no = 1:length(setstruct) setstruct(no).GEVENCSCALE = 0; - end; -end; + end +end %Check if there are any autolongaxis, and ask to reset for no = 1:length(setstruct) if ~isfield(setstruct(no), 'AutoLongaxis') || isempty(setstruct(no).AutoLongaxis) setstruct(no).AutoLongaxis = false; end -end; +end autolongaxis = cat(1,setstruct.AutoLongaxis) & (cat(1,setstruct.TSize)>1); autolongaxis = sum(autolongaxis); @@ -453,26 +426,26 @@ for no = 1:length(setstruct) setstruct(no).AutoLongaxis = false; setstruct(no).Longaxis = 1; - end; - end; -end; + end + end +end if not(isfield(setstruct,'Longaxis')) for no = 1:length(setstruct) setstruct(no).Longaxis = 1; %Remove this from default, EH: 2017-06-19, 1=>first choice in listbox => 0. Was 1 before as well... - end; -end; + end +end for no = 1:length(setstruct) if isempty(setstruct(no).Longaxis) setstruct(no).Longaxis = 1; %Remove this from default, EH: 2017-06-19, 1=>first choice in listbox => 0. Was 1 before as well... - end; -end; + end +end if not(isfield(setstruct,'AutoLongaxis')) for no = 1:length(setstruct) setstruct(no).AutoLongaxis = false; %Remove this from default, EH: 2017-06-19 - end; + end else for no = 1:length(setstruct) if isempty(setstruct(no).AutoLongaxis) @@ -485,14 +458,14 @@ if not(isfield(setstruct,'Strain')) for no = 1:length(setstruct) setstruct(no).Strain = []; - end; -end; + end +end if not(isfield(setstruct,'StrainTagging')) for no = 1:length(setstruct) setstruct(no).StrainTagging = []; - end; -end; + end +end %RV field check if not(isfield(setstruct,'RVEndoX')) @@ -501,8 +474,8 @@ setstruct(no).RVEndoY = []; setstruct(no).RVEpiX = []; setstruct(no).RVEpiY = []; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).RVEndoX) setstruct(no).RVEndoX = []; @@ -511,8 +484,8 @@ if isempty(setstruct(no).RVEpiX) setstruct(no).RVEpiX = []; setstruct(no).RVEpiY = []; - end; -end; + end +end if not(isfield(setstruct,'RVEndoPinX')) for no=1:length(setstruct) @@ -524,8 +497,8 @@ setstruct(no).RVEpiPinY = []; setstruct(no).RVEpiPinXView = []; setstruct(no).RVEpiPinYView = []; - end; -end; + end +end if not(isfield(setstruct,'EndoInterpX')) for no=1:length(setstruct) @@ -537,8 +510,8 @@ setstruct(no).RVEndoInterpY = []; setstruct(no).RVEpiInterpX = []; setstruct(no).RVEpiInterpY = []; - end; -end; + end +end if not(isfield(setstruct,'RVV')) for no = 1:length(setstruct) @@ -549,8 +522,8 @@ setstruct(no).RVESV = 0; setstruct(no).RVSV = 0; setstruct(no).RVEF = 0; - end; -end; + end +end %--- Point check if not(isfield(setstruct,'Point')) @@ -560,8 +533,8 @@ setstruct(no).Point.T = []; setstruct(no).Point.Z = []; setstruct(no).Point.Label = {}; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).Point) setstruct(no).Point.X = []; @@ -569,8 +542,22 @@ setstruct(no).Point.T = []; setstruct(no).Point.Z = []; setstruct(no).Point.Label = {}; - end; -end; + end +end + +%--- 3D Point check +if not(isfield(setstruct,'Point3D')) + for no = 1:length(setstruct) + setstruct(no).Point3D.X = []; + setstruct(no).Point3D.Y = []; + end +end +for no=1:length(setstruct) + if isempty(setstruct(no).Point3D) + setstruct(no).Point3D.X = []; + setstruct(no).Point3D.Y = []; + end +end %--- IntensityMapping if not(isfield(setstruct,'IntensityMapping')) @@ -578,15 +565,15 @@ setstruct(no).IntensityMapping.Brightness = 0.5; setstruct(no).IntensityMapping.Contrast = 1; setstruct(no).IntensityMapping.Compression = []; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).IntensityMapping) setstruct(no).IntensityMapping.Brightness = 0.5; setstruct(no).IntensityMapping.Contrast = 1; setstruct(no).IntensityMapping.Compression = []; - end; -end; + end +end for no=1:length(setstruct) if ~isfield(setstruct(no),'Colormap') %||isempty(setstruct(no).Colormap) @@ -594,7 +581,7 @@ % setstruct(no).Colormap = gray(256); setstruct(no).Colormap = []; end -end; +end for loop = 1:length(setstruct) if isempty(setstruct(no).PatientInfo) @@ -606,39 +593,39 @@ setstruct(no).PatientInfo.BSA = 0; setstruct(no).PatientInfo.Weight = 0; setstruct(no).PatientInfo.Length = 0; - end; -end; + end +end for no = 1:length(setstruct) if ~isfield(setstruct(no).PatientInfo,'BSA') setstruct(no).PatientInfo.BSA = 0; - end; -end; + end +end for no = 1:length(setstruct) if setstruct(no).PatientInfo.BSA==0 setstruct(no).PatientInfo.BSA = calcfunctions('calcbsa',... setstruct(no).PatientInfo.Weight,... setstruct(no).PatientInfo.Length); - end; -end; + end +end for no = 1:length(setstruct) if isequal(setstruct(no).Flow,0) setstruct(no).Flow = []; - end; + end if not(isempty(setstruct(no).Flow)) if not(isfield(setstruct(no).Flow,'PhaseX')) setstruct(no).Flow.PhaseX = []; setstruct(no).Flow.PhaseY = []; - end; + end if not(isfield(setstruct(no).Flow,'Angio')) setstruct(no).Flow.Angio = []; setstruct(no).Flow.VelMag = []; - end; + end if not(isfield(setstruct(no).Flow,'PhaseNo')) setstruct(no).Flow.PhaseNo = []; - end; + end if not(isfield(setstruct(no).Flow,'Result')) if isfield(setstruct(no).Flow,'nettotvol') try @@ -662,117 +649,141 @@ else setstruct(no).Flow.Result = []; end - end; + end if isfield(setstruct(no).Flow,'parameter') if not(isfield(setstruct(no).Flow.parameter,'expandoutward')) setstruct(no).Flow.parameter.expandoutward = 0; %mm %This will probably be changed when we know that this is a good idea. - end; - end; - end; -end; + end + end + end +end %--- ImagePosition if not(isfield(setstruct,'ImagePosition')) for no = 1:length(setstruct) setstruct(no).ImagePosition = [0 0 0]; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).ImagePosition) setstruct(no).ImagePosition = [0 0 0]; - end; -end; + end +end %--- ImageOrientation if not(isfield(setstruct,'ImageOrientation')) for no = 1:length(setstruct) setstruct(no).ImageOrientation = [1 0 0 0 1 0]; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).ImageOrientation) setstruct(no).ImageOrientation = [1 0 0 0 1 0]; - end; -end; + end +end + +%--- RotatedImagePosition +if not(isfield(setstruct,'RotatedImagePosition')) + for no = 1:length(setstruct) + setstruct(no).RotatedImagePosition = setstruct(no).ImagePosition; + end +end +for no=1:length(setstruct) + if isempty(setstruct(no).RotatedImagePosition) + setstruct(no).RotatedImagePosition = setstruct(no).ImagePosition; + end +end + +%--- RotatedImageOrientation +if not(isfield(setstruct,'RotatedImageOrientation')) + for no = 1:length(setstruct) + setstruct(no).RotatedImageOrientation = setstruct(no).ImageOrientation; + end +end +for no=1:length(setstruct) + if isempty(setstruct(no).RotatedImageOrientation) + setstruct(no).RotatedImageOrientation = setstruct(no).ImageOrientation; + end +end %--- EchoTime if not(isfield(setstruct,'EchoTime')) for no = 1:length(setstruct) setstruct(no).EchoTime = 0; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).EchoTime) setstruct(no).EchoTime = 0; - end; -end; + end +end %--- RepetitionTime if not(isfield(setstruct,'RepetitionTime')) for no = 1:length(setstruct) setstruct(no).RepetitionTime = 0; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).RepetitionTime) setstruct(no).RepetitionTime = 0; - end; -end; + end +end %--- InversionTime if not(isfield(setstruct,'InversionTime')) for no = 1:length(setstruct) setstruct(no).InversionTime = 0; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).InversionTime) setstruct(no).InversionTime = 0; - end; -end; + end +end %--- FlipAngle if not(isfield(setstruct,'FlipAngle')) for no = 1:length(setstruct) setstruct(no).FlipAngle = 0; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).FlipAngle) setstruct(no).FlipAngle = 0; - end; -end; + end +end %--- NumberOfAverages if not(isfield(setstruct,'NumberOfAverages')) for no = 1:length(setstruct) setstruct(no).NumberOfAverages = 0; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).NumberOfAverages) setstruct(no).NumberOfAverages = 0; - end; -end; + end +end %--- Scanner if not(isfield(setstruct,'Scanner')) for no = 1:length(setstruct) setstruct(no).Scanner = ''; - end; -end; + end +end for no=1:length(setstruct) if isempty(setstruct(no).Scanner) setstruct(no).Scanner = ''; - end; -end; + end +end %--- View if not(isfield(setstruct,'View')) for no = 1:length(setstruct) setstruct(no).View = []; - end; + end %--- ViewPanelsMatrix subfield elseif not(isempty(setstruct(1).View)) && not(isfield(setstruct(1).View,'ViewPanelsMatrix')) panels = setstruct(1).View.ViewPanels; @@ -785,89 +796,97 @@ end setstruct(1).View.ViewPanelsMatrix{i} = [rows cols]; end -end; +elseif not(isempty(setstruct(1).View)) && not(isfield(setstruct(1).View,'LVNO')) + setstruct(1).View.LVNO = []; + setstruct(1).View.RVNO = []; + setstruct(1).View.FlowNO = []; + setstruct(1).View.FlowROI = []; +end +if not(isempty(setstruct(1).View)) && not(isfield(setstruct(1).View,'CurrentTheme')) + setstruct(1).View.CurrentTheme = 'lv'; +end %--- RotationCenter if not(isfield(setstruct,'RotationCenter')) setstruct(1).RotationCenter = []; -end; +end for loop = 1:length(setstruct) if setstruct(loop).Rotated if isempty(setstruct(loop).RotationCenter) setstruct(loop).RotationCenter = setstruct(loop).OrgYSize/2-setstruct(loop).YMin; - end; - end; -end; + end + end +end if not(isfield(setstruct,'SequenceName')) setstruct(1).SequenceName = ''; -end; +end for loop = 1:length(setstruct) if isempty(setstruct(loop).SequenceName) setstruct(loop).SequenceName = ''; - end; -end; + end +end if not(isfield(setstruct,'SeriesDescription')) setstruct(1).SeriesDescription = ''; -end; +end for loop = 1:length(setstruct) if isempty(setstruct(loop).SeriesDescription) setstruct(loop).SeriesDescription = ''; - end; -end; + end +end if not(isfield(setstruct,'DICOMImageType')) setstruct(1).DICOMImageType = ''; -end; +end for loop = 1:length(setstruct) if isempty(setstruct(loop).DICOMImageType) setstruct(loop).DICOMImageType = ''; - end; -end; + end +end if not(isfield(setstruct,'Fusion')) setstruct(1).Fusion = []; -end; +end %EH,JT: Fix for backwards compability of .mat files with %2D or 3D flow. setstruct(1).ProgramVersion = DATA.ProgramVersion; for loop=1:length(setstruct) setstruct(loop).ProgramVersion = setstruct(1).ProgramVersion; -end; +end % Backwards compability for old pin structs for loop=1:length(setstruct) - if not(isempty(setstruct(loop).EndoPinX)) && all(all(cellfun('isempty',setstruct(loop).EndoPinX))) - setstruct(loop).EndoPinX = []; - setstruct(loop).EndoPinY = []; - end; - if not(isempty(setstruct(loop).EpiPinX)) && all(all(cellfun('isempty',setstruct(loop).EpiPinX))) - setstruct(loop).EpiPinX = []; - setstruct(loop).EpiPinY = []; - end; - if not(isempty(setstruct(loop).RVEndoPinX)) && all(all(cellfun('isempty',setstruct(loop).RVEndoPinX))) - setstruct(loop).RVEndoPinX = []; - setstruct(loop).RVEndoPinY = []; - end; - if not(isempty(setstruct(loop).RVEpiPinX)) && all(all(cellfun('isempty',setstruct(loop).RVEpiPinX))) - setstruct(loop).RVEpiPinX = []; - setstruct(loop).RVEpiPinY = []; - end; -end; + if not(isempty(setstruct(loop).EndoPinX)) && all(all(cellfun('isempty',setstruct(loop).EndoPinX))) + setstruct(loop).EndoPinX = []; + setstruct(loop).EndoPinY = []; + end + if not(isempty(setstruct(loop).EpiPinX)) && all(all(cellfun('isempty',setstruct(loop).EpiPinX))) + setstruct(loop).EpiPinX = []; + setstruct(loop).EpiPinY = []; + end + if not(isempty(setstruct(loop).RVEndoPinX)) && all(all(cellfun('isempty',setstruct(loop).RVEndoPinX))) + setstruct(loop).RVEndoPinX = []; + setstruct(loop).RVEndoPinY = []; + end + if not(isempty(setstruct(loop).RVEpiPinX)) && all(all(cellfun('isempty',setstruct(loop).RVEpiPinX))) + setstruct(loop).RVEpiPinX = []; + setstruct(loop).RVEpiPinY = []; + end +end if not(isfield(setstruct,'AcquisitionTime')) for no = 1:length(setstruct) setstruct(no).AcquisitionTime = 0; - end; -end; + end +end if not(isfield(setstruct,'SeriesNumber')) for no = 1:length(setstruct) setstruct(no).SeriesNumber = ''; - end; -end; + end +end if not(isfield(setstruct,'PapillaryIM')) for no=1:length(setstruct) @@ -886,10 +905,24 @@ if all(cellfun(@isempty,setstruct(no).EndoInterpX)) setstruct(no).EndoInterpX=[]; setstruct(no).EndoInterpY=[]; - elseif size(setstruct(no).EndoInterpX,1)~=setstruct(no).TSize %&& size(setstruct(no).EndoInterpX,2)==setstruct(no).ZSize)pad=cell(size(setstruct(no).TSize-setstruct(no).EndoInterpX,1),... - pad = cell(setstruct(no).TSize-size(setstruct(no).EndoInterpX,1),setstruct(no).ZSize); - setstruct(no).EndoInterpX=[setstruct(no).EndoInterpX;pad]; - setstruct(no).EndoInterpY=[setstruct(no).EndoInterpY;pad]; + else + correcttsize = (size(setstruct(no).EndoInterpX,1) == setstruct(no).TSize); + correctzsize = (size(setstruct(no).EndoInterpX,2) == setstruct(no).ZSize); + if not(correcttsize) && correctzsize + try + pad = cell(setstruct(no).TSize-size(setstruct(no).EndoInterpX,1),setstruct(no).ZSize); + setstruct(no).EndoInterpX=[setstruct(no).EndoInterpX;pad]; + setstruct(no).EndoInterpY=[setstruct(no).EndoInterpY;pad]; + catch + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).EndoInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).EndoInterpY = setstruct(no).EndoInterpX; + end + elseif not(correctzsize) + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).EndoInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).EndoInterpY = setstruct(no).EndoInterpX; + end end end @@ -897,10 +930,24 @@ if all(cellfun(@isempty,setstruct(no).EpiInterpX)) setstruct(no).EpiInterpX=[]; setstruct(no).EpiInterpY=[]; - elseif size(setstruct(no).EpiInterpX,1)~=setstruct(no).TSize %&& size(setstruct(no).EndoInterpX,2)==setstruct(no).ZSize)pad=cell(size(setstruct(no).TSize-setstruct(no).EndoInterpX,1),... - pad = cell(setstruct(no).TSize-size(setstruct(no).EpiInterpX,1),setstruct(no).ZSize); - setstruct(no).EpiInterpX=[setstruct(no).EpiInterpX;pad]; - setstruct(no).EpiInterpY=[setstruct(no).EpiInterpY;pad]; + else + correcttsize = (size(setstruct(no).EpiInterpX,1) == setstruct(no).TSize); + correctzsize = (size(setstruct(no).EpiInterpX,2) == setstruct(no).ZSize); + if not(correcttsize) && correctzsize + try + pad = cell(setstruct(no).TSize-size(setstruct(no).EpiInterpX,1),setstruct(no).ZSize); + setstruct(no).EpiInterpX=[setstruct(no).EpiInterpX;pad]; + setstruct(no).EpiInterpY=[setstruct(no).EpiInterpY;pad]; + catch + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).EpiInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).EpiInterpY = setstruct(no).EpiInterpX; + end + elseif not(correctzsize) + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).EpiInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).EpiInterpY = setstruct(no).EpiInterpX; + end end end @@ -908,12 +955,24 @@ if all(cellfun(@isempty,setstruct(no).RVEndoInterpX)) setstruct(no).RVEndoInterpX=[]; setstruct(no).RVEndoInterpY=[]; - elseif size(setstruct(no).RVEndoInterpX,1)~=setstruct(no).TSize %&& size(setstruct(no).EndoInterpX,2)==setstruct(no).ZSize)pad=cell(size(setstruct(no).TSize-setstruct(no).EndoInterpX,1),... - setstruct(no).RVEndoInterpX=[]; - setstruct(no).RVEndoInterpY=[]; - % pad = cell(setstruct(no).TSize-size(setstruct(no).RVEndoInterpX,1),setstruct(no).ZSize); -% setstruct(no).RVEndoInterpX=[setstruct(no).RVEndoInterpX;pad]; -% setstruct(no).RVEndoInterpY=[setstruct(no).RVEndoInterpY;pad]; + else + correcttsize = (size(setstruct(no).RVEndoInterpX,1) == setstruct(no).TSize); + correctzsize = (size(setstruct(no).RVEndoInterpX,2) == setstruct(no).ZSize); + if not(correcttsize) && correctzsize + try + pad = cell(setstruct(no).TSize-size(setstruct(no).RVEndoInterpX,1),setstruct(no).ZSize); + setstruct(no).RVEndoInterpX=[setstruct(no).RVEndoInterpX;pad]; + setstruct(no).RVEndoInterpY=[setstruct(no).RVEndoInterpY;pad]; + catch + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).RVEndoInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).RVEndoInterpY = setstruct(no).RVEndoInterpX; + end + elseif not(correctzsize) + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).RVEndoInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).RVEndoInterpY = setstruct(no).RVEndoInterpX; + end end end @@ -921,10 +980,24 @@ if all(cellfun(@isempty,setstruct(no).RVEpiInterpX)) setstruct(no).RVEpiInterpX=[]; setstruct(no).RVEpiInterpY=[]; - elseif size(setstruct(no).RVEpiInterpX,1)~=setstruct(no).TSize %&& size(setstruct(no).EndoInterpX,2)==setstruct(no).ZSize)pad=cell(size(setstruct(no).TSize-setstruct(no).EndoInterpX,1),... - pad = cell(setstruct(no).TSize-size(setstruct(no).RVEpiInterpX,1),setstruct(no).ZSize); - setstruct(no).RVEpiInterpX=[setstruct(no).RVEpiInterpX;pad]; - setstruct(no).RVEpiInterpY=[setstruct(no).RVEpiInterpY;pad]; + else + correcttsize = (size(setstruct(no).RVEpiInterpX,1) == setstruct(no).TSize); + correctzsize = (size(setstruct(no).RVEpiInterpX,2) == setstruct(no).ZSize); + if not(correcttsize) && correctzsize + try + pad = cell(setstruct(no).TSize-size(setstruct(no).RVEpiInterpX,1),setstruct(no).ZSize); + setstruct(no).RVEpiInterpX=[setstruct(no).RVEpiInterpX;pad]; + setstruct(no).RVEpiInterpY=[setstruct(no).RVEpiInterpY;pad]; + catch + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).RVEpiInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).RVEpiInterpY = setstruct(no).RVEpiInterpX; + end + elseif not(correctzsize) + disp('Issue in reading RV interpolation points. Deleting the points.'); + setstruct(no).RVEpiInterpX = cell(setstruct(no).TSize,setstruct(no).ZSize); + setstruct(no).RVEpiInterpY = setstruct(no).RVEpiInterpX; + end end end end @@ -938,11 +1011,11 @@ setstruct(no).EndoInterpX{tloop,sloop} = setstruct(no).EndoInterpX{tloop,sloop}(:); setstruct(no).EndoInterpY{tloop,sloop} = setstruct(no).EndoInterpY{tloop,sloop}(:); disp('Warning interpolation point size error. Now fixed.'); - end; - end; - end; - end; -end; + end + end + end + end +end for no = 1:length(setstruct) if ~isempty(setstruct(no).EpiInterpX) @@ -952,11 +1025,11 @@ setstruct(no).EpiInterpX{tloop,sloop} = setstruct(no).EpiInterpX{tloop,sloop}(:); setstruct(no).EpiInterpY{tloop,sloop} = setstruct(no).EpiInterpY{tloop,sloop}(:); disp('Warning interpolation point size error. Now fixed.'); - end; - end; - end; - end; -end; + end + end + end + end +end for no = 1:length(setstruct) if ~isempty(setstruct(no).RVEndoInterpX) @@ -966,11 +1039,11 @@ setstruct(no).RVEndoInterpX{tloop,sloop} = setstruct(no).RVEndoInterpX{tloop,sloop}(:); setstruct(no).RVEndoInterpY{tloop,sloop} = setstruct(no).RVEndoInterpY{tloop,sloop}(:); disp('Warning interpolation point size error. Now fixed.'); - end; - end; - end; - end; -end; + end + end + end + end +end for no = 1:length(setstruct) if ~isempty(setstruct(no).RVEpiInterpX) @@ -980,20 +1053,20 @@ setstruct(no).RVEpiInterpX{tloop,sloop} = setstruct(no).RVEpiInterpX{tloop,sloop}(:); setstruct(no).RVEpiInterpY{tloop,sloop} = setstruct(no).RVEpiInterpY{tloop,sloop}(:); disp('Warning interpolation point size error. Now fixed.'); - end; - end; - end; - end; -end; + end + end + end + end +end %set image view plane based on old image type definition -if ~isfield(setstruct,'ImageViewPlane'); +if ~isfield(setstruct,'ImageViewPlane') for no = 1:length(setstruct) oldImageType = setstruct(no).ImageType; [type,viewplane] = segment('imagedescription'); settype = 0; setviewplane = 0; - if isfield(setstruct,'ImageType'); + if isfield(setstruct,'ImageType') for typeloop = 1:length(type) if findstr(lower(oldImageType),lower(type{typeloop})) %#ok setstruct(no).ImageType = type{typeloop}; @@ -1036,7 +1109,7 @@ end end end -if isfield(setstruct,'MaRIM'); +if isfield(setstruct,'MaRIM') setstruct=rmfield(setstruct,'MaRIM'); end for no=1:length(setstruct) @@ -1127,7 +1200,7 @@ if not(isempty(setstruct(no).Measure)) && not(isfield(setstruct(no).Measure,'LongName')) for sloop = 1:length(setstruct(no).Measure) setstruct(no).Measure(sloop).LongName = setstruct(no).Measure(sloop).Name; - end; + end end end @@ -1181,29 +1254,29 @@ if not(isfield(setstruct,'AccessionNumber')) for no = 1:length(setstruct) setstruct(no).AccessionNumber = ''; - end; -end; + end +end %--- StudyID if not(isfield(setstruct,'StudyID')) for no = 1:length(setstruct) setstruct(no).StudyID = ''; end -end; +end %--- StudyUID if not(isfield(setstruct,'StudyUID')) for no = 1:length(setstruct) setstruct(no).StudyUID = ''; - end; -end; + end +end %--- Intersection if not(isfield(setstruct,'Intersection')) for no = 1:length(setstruct) setstruct(no).Intersection = []; - end; -end; + end +end %Bug check for EST and EDT if its zero for no = 1:length(setstruct) @@ -1229,22 +1302,30 @@ end end +for no = 1:length(setstruct) + if (isempty(setstruct(no).CurrentSlice)) + setstruct(no).CurrentSlice = 1; + setstruct(no).EndSlice = 1; + setstruct(no).StartSlice = 1; + end +end + %--- Comment if not(isfield(setstruct,'Comment')) setstruct(1).Comment = []; -end; +end %--- AtrialScar if not(isfield(setstruct,'AtrialScar')) setstruct(1).AtrialScar = []; -end; +end %--- PatientInfo -> Institution for no = 1:length(setstruct) if ~isfield(setstruct(no).PatientInfo,'Institution') setstruct(no).PatientInfo.Institution = ''; - end; -end; + end +end %--- PatientInfo -> Remove obsolete HeartRate field (later) % for no = 1:length(setstruct) @@ -1254,6 +1335,14 @@ % end; % end +%--- LastUserInfo +for no = 1:length(setstruct) + if ~isfield(setstruct(no),'LastUserInfo') + setstruct(no).LastUserInfo = ''; + end +end + + %--- Extra views for SPECT if ~isfield(setstruct,'HLA') [setstruct.SAX3] = deal([]); @@ -1306,122 +1395,140 @@ [setstruct.Developer] = deal([]); end +if ~isfield(setstruct,'Line3D') + %Used for 3D lines in Segment 3DP + for loop = 1:length(setstruct) + setstruct(loop).Line3D = []; + setstruct(loop).Line3D.X = {}; + setstruct(loop).Line3D.Y = {}; + setstruct(loop).Line3D.Z = {}; + setstruct(loop).Line3D.Points = {}; + setstruct(loop).Line3D.Closed = []; + setstruct(loop).Line3D.Sigma = []; + end +end + +if ~isfield(setstruct,'PVLoop') + %Used for the PV-loop module + setstruct(1).PVLoop = []; %empty is enough to initialise as +end + %%%%%%%%%%%%% %%% Check validity of fields %%% %%%%%%%%%%%%% %Check if valid interpx for no = 1:length(setstruct) - if ~isempty(setstruct(no).EndoInterpX) && not(isempty(setstruct(no).EndoX)) - for tloop=1:setstruct(no).TSize - for sloop=1:setstruct(no).ZSize - if not(isempty(setstruct(no).EndoInterpX{tloop,sloop})) && not(isnan(setstruct(no).EndoX(1,tloop,sloop))) - ipx=setstruct(no).EndoInterpX{tloop,sloop}; - ipy=setstruct(no).EndoInterpY{tloop,sloop}; - contx = setstruct(no).EndoX(:,tloop,sloop); - conty = setstruct(no).EndoY(:,tloop,sloop); - - ipxrep=repmat(ipx',[length(contx) 1]); - contxrep=repmat(contx,[1 length(ipx)]); - ipyrep=repmat(ipy',[length(conty) 1]); - contyrep=repmat(conty,[1 length(ipy)]); - pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; - [~,mindistindex] = min(pindist2cont); - [~,sortindex] = sort(mindistindex); - ipx=ipx(sortindex); - ipy=ipy(sortindex); - - setstruct(no).EndoInterpX{tloop,sloop}=ipx; - setstruct(no).EndoInterpY{tloop,sloop}=ipy; - end; - end; - end; - end; -end; + if ~isempty(setstruct(no).EndoInterpX) && not(isempty(setstruct(no).EndoX)) + for tloop=1:setstruct(no).TSize + for sloop=1:setstruct(no).ZSize + if not(isempty(setstruct(no).EndoInterpX{tloop,sloop})) && not(isnan(setstruct(no).EndoX(1,tloop,sloop))) + ipx=setstruct(no).EndoInterpX{tloop,sloop}; + ipy=setstruct(no).EndoInterpY{tloop,sloop}; + contx = setstruct(no).EndoX(:,tloop,sloop); + conty = setstruct(no).EndoY(:,tloop,sloop); + + ipxrep=repmat(ipx',[length(contx) 1]); + contxrep=repmat(contx,[1 length(ipx)]); + ipyrep=repmat(ipy',[length(conty) 1]); + contyrep=repmat(conty,[1 length(ipy)]); + pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; + [~,mindistindex] = min(pindist2cont); + [~,sortindex] = sort(mindistindex); + ipx=ipx(sortindex); + ipy=ipy(sortindex); + + setstruct(no).EndoInterpX{tloop,sloop}=ipx; + setstruct(no).EndoInterpY{tloop,sloop}=ipy; + end + end + end + end +end for no = 1:length(setstruct) - if ~isempty(setstruct(no).EpiInterpX) && not(isempty(setstruct(no).EpiX)) - for tloop=1:setstruct(no).TSize - for sloop=1:setstruct(no).ZSize - if not(isempty(setstruct(no).EpiInterpX{tloop,sloop})) && not(isnan(setstruct(no).EpiX(1,tloop,sloop))) - ipx=setstruct(no).EpiInterpX{tloop,sloop}; - ipy=setstruct(no).EpiInterpY{tloop,sloop}; - contx = setstruct(no).EpiX(:,tloop,sloop); - conty = setstruct(no).EpiY(:,tloop,sloop); - - ipxrep=repmat(ipx',[length(contx) 1]); - contxrep=repmat(contx,[1 length(ipx)]); - ipyrep=repmat(ipy',[length(conty) 1]); - contyrep=repmat(conty,[1 length(ipy)]); - pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; - [~,mindistindex] = min(pindist2cont); - [~,sortindex] = sort(mindistindex); - ipx=ipx(sortindex); - ipy=ipy(sortindex); - - setstruct(no).EpiInterpX{tloop,sloop}=ipx; - setstruct(no).EpiInterpY{tloop,sloop}=ipy; - end; - end; - end; - end; -end; + if ~isempty(setstruct(no).EpiInterpX) && not(isempty(setstruct(no).EpiX)) + for tloop=1:setstruct(no).TSize + for sloop=1:setstruct(no).ZSize + if not(isempty(setstruct(no).EpiInterpX{tloop,sloop})) && not(isnan(setstruct(no).EpiX(1,tloop,sloop))) + ipx=setstruct(no).EpiInterpX{tloop,sloop}; + ipy=setstruct(no).EpiInterpY{tloop,sloop}; + contx = setstruct(no).EpiX(:,tloop,sloop); + conty = setstruct(no).EpiY(:,tloop,sloop); + + ipxrep=repmat(ipx',[length(contx) 1]); + contxrep=repmat(contx,[1 length(ipx)]); + ipyrep=repmat(ipy',[length(conty) 1]); + contyrep=repmat(conty,[1 length(ipy)]); + pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; + [~,mindistindex] = min(pindist2cont); + [~,sortindex] = sort(mindistindex); + ipx=ipx(sortindex); + ipy=ipy(sortindex); + + setstruct(no).EpiInterpX{tloop,sloop}=ipx; + setstruct(no).EpiInterpY{tloop,sloop}=ipy; + end + end + end + end +end for no = 1:length(setstruct) - if ~isempty(setstruct(no).RVEndoInterpX) && not(isempty(setstruct(no).RVEndoX)) - for tloop=1:setstruct(no).TSize - for sloop=1:setstruct(no).ZSize - if not(isempty(setstruct(no).RVEndoInterpX{tloop,sloop})) && not(isnan(setstruct(no).RVEndoX(1,tloop,sloop))) - ipx=setstruct(no).RVEndoInterpX{tloop,sloop}; - ipy=setstruct(no).RVEndoInterpY{tloop,sloop}; - contx = setstruct(no).RVEndoX(:,tloop,sloop); - conty = setstruct(no).RVEndoY(:,tloop,sloop); - - ipxrep=repmat(ipx',[length(contx) 1]); - contxrep=repmat(contx,[1 length(ipx)]); - ipyrep=repmat(ipy',[length(conty) 1]); - contyrep=repmat(conty,[1 length(ipy)]); - pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; - [~,mindistindex] = min(pindist2cont); - [~,sortindex] = sort(mindistindex); - ipx=ipx(sortindex); - ipy=ipy(sortindex); - - setstruct(no).RVEndoInterpX{tloop,sloop}=ipx; - setstruct(no).RVEndoInterpY{tloop,sloop}=ipy; - end; - end; - end; - end; -end; + if ~isempty(setstruct(no).RVEndoInterpX) && not(isempty(setstruct(no).RVEndoX)) + for tloop=1:setstruct(no).TSize + for sloop=1:setstruct(no).ZSize + if not(isempty(setstruct(no).RVEndoInterpX{tloop,sloop})) && not(isnan(setstruct(no).RVEndoX(1,tloop,sloop))) + ipx=setstruct(no).RVEndoInterpX{tloop,sloop}; + ipy=setstruct(no).RVEndoInterpY{tloop,sloop}; + contx = setstruct(no).RVEndoX(:,tloop,sloop); + conty = setstruct(no).RVEndoY(:,tloop,sloop); + + ipxrep=repmat(ipx',[length(contx) 1]); + contxrep=repmat(contx,[1 length(ipx)]); + ipyrep=repmat(ipy',[length(conty) 1]); + contyrep=repmat(conty,[1 length(ipy)]); + pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; + [~,mindistindex] = min(pindist2cont); + [~,sortindex] = sort(mindistindex); + ipx=ipx(sortindex); + ipy=ipy(sortindex); + + setstruct(no).RVEndoInterpX{tloop,sloop}=ipx; + setstruct(no).RVEndoInterpY{tloop,sloop}=ipy; + end + end + end + end +end for no = 1:length(setstruct) - if ~isempty(setstruct(no).RVEpiInterpX) && not(isempty(setstruct(no).RVEpiX)) - for tloop=1:setstruct(no).TSize - for sloop=1:setstruct(no).ZSize - if not(isempty(setstruct(no).RVEpiInterpX{tloop,sloop})) && not(isnan(setstruct(no).RVEpiX(1,tloop,sloop))) - ipx=setstruct(no).RVEpiInterpX{tloop,sloop}; - ipy=setstruct(no).RVEpiInterpY{tloop,sloop}; - contx = setstruct(no).RVEpiX(:,tloop,sloop); - conty = setstruct(no).RVEpiY(:,tloop,sloop); - - ipxrep=repmat(ipx',[length(contx) 1]); - contxrep=repmat(contx,[1 length(ipx)]); - ipyrep=repmat(ipy',[length(conty) 1]); - contyrep=repmat(conty,[1 length(ipy)]); - pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; - [~,mindistindex] =min(pindist2cont); - [~,sortindex] =sort(mindistindex); - ipx=ipx(sortindex); - ipy=ipy(sortindex); - - setstruct(no).RVEpiInterpX{tloop,sloop}=ipx; - setstruct(no).RVEpiInterpY{tloop,sloop}=ipy; - end; - end; - end; - end; -end; + if ~isempty(setstruct(no).RVEpiInterpX) && not(isempty(setstruct(no).RVEpiX)) + for tloop=1:setstruct(no).TSize + for sloop=1:setstruct(no).ZSize + if not(isempty(setstruct(no).RVEpiInterpX{tloop,sloop})) && not(isnan(setstruct(no).RVEpiX(1,tloop,sloop))) + ipx=setstruct(no).RVEpiInterpX{tloop,sloop}; + ipy=setstruct(no).RVEpiInterpY{tloop,sloop}; + contx = setstruct(no).RVEpiX(:,tloop,sloop); + conty = setstruct(no).RVEpiY(:,tloop,sloop); + + ipxrep=repmat(ipx',[length(contx) 1]); + contxrep=repmat(contx,[1 length(ipx)]); + ipyrep=repmat(ipy',[length(conty) 1]); + contyrep=repmat(conty,[1 length(ipy)]); + pindist2cont = (ipxrep-contxrep).^2+(ipyrep-contyrep).^2; + [~,mindistindex] =min(pindist2cont); + [~,sortindex] =sort(mindistindex); + ipx=ipx(sortindex); + ipy=ipy(sortindex); + + setstruct(no).RVEpiInterpX{tloop,sloop}=ipx; + setstruct(no).RVEpiInterpY{tloop,sloop}=ipy; + end + end + end + end +end %%%%%%%%%%%%% %%% Obsolete fields @@ -1431,17 +1538,17 @@ % setstruct = rmfield(setstruct,'Colormap'); %end; -if isfield(setstruct,'CurrentTool'); +if isfield(setstruct,'CurrentTool') setstruct = rmfield(setstruct,'CurrentTool'); -end; +end -if isfield(setstruct,'Model'); +if isfield(setstruct,'Model') setstruct = rmfield(setstruct,'Model'); -end; +end if isfield(setstruct,'ViewMode') setstruct = rmfield(setstruct,'ViewMode'); -end; +end if isfield(setstruct,'rows') setstruct = rmfield(setstruct,{'rows','cols'}); @@ -1455,4 +1562,14 @@ SET = setstruct; end - +%------------------------------------------------------------------- +function fieldvalues = rebuildflowresults(fieldvalues,numtimeframes) +%------------------------------------------------------------------- +% rewrites flow results so that their length correspond to the number of +% time frames and existing values are placed in the corrsponding places and +% arraz indexes without values are set to NaN + +[~,ind] = find(fieldvalues); +newvalues = nan(1,numtimeframes); +newvalues(ind) = fieldvalues(ind); +fieldvalues = newvalues; diff --git a/source/loadpreferences.m b/source/loadpreferences.m index 29643af..d614ce3 100644 --- a/source/loadpreferences.m +++ b/source/loadpreferences.m @@ -14,35 +14,26 @@ if ispc if not(exist([pathname filesep '.segment_preferences.mat'],'file')) %mywarning('Moving system preferences file to new user location.'); - mydisp('Moving system preferences file to new user location.'); + disp('Moving system preferences file to new user location.'); %Old old location if exist('preferences.mat','file') - mymovefile([pwd filesep 'preferences.mat'],[pathname filesep '.segment_preferences.mat']); - % dos(sprintf('move "%s" "%s"',... - % [pwd filesep 'preferences.mat'],... - % [pathname filesep '.segment_preferences.mat'])); + mymovefile([DATA.SegmentFolder filesep 'preferences.mat'],[pathname filesep '.segment_preferences.mat']); elseif exist('default_preferences.mat','file') - mycopyfile([pwd filesep 'default_preferences.mat'],[pathname filesep '.segment_preferences.mat']); - end; + mycopyfile([DATA.SegmentFolder filesep 'default_preferences.mat'],[pathname filesep '.segment_preferences.mat']); + end %old location just try it... - mymovefile([pwd filesep '.segment_preferences.mat'],[pathname filesep '.segment_preferences.mat']); - % dos(sprintf('move "%s%s..%s%s" "%s%s%s"',... - % pathname,filesep,filesep,'.segment_preferences.mat',... - % pathname,filesep,'.segment_preferences.mat'));%Det gar inte att hitta filen. - - %Remove old log file - %dos(sprintf('delete "%s%s..%s%s"',pathname,filesep,filesep,'.segment.log'));%delete ar inte ett internt kommando, externt kommando, program eller kommandofil. + mymovefile([DATA.SegmentFolder filesep '.segment_preferences.mat'],[pathname filesep '.segment_preferences.mat']); end -end; +end %Try to find a more suitable place for the try load([pathname filesep '.segment_preferences.mat'],'Pref'); catch %#ok - mydisp('Could not read preferences. Probably a new installation.'); - Pref.datapath = [pwd filesep 'Examples']; + disp('Could not read preferences. Probably a new installation.'); + Pref.datapath = [DATA.SegmentFolder filesep 'Examples']; Pref.exportpath = Pref.datapath; Pref.AnonymMode = false; Pref.AddPoints = false; @@ -51,9 +42,8 @@ DATA.defaultpref; Pref = DATA.Pref; savetodisk; %Save the preferences to disk -end; +end DATA.Pref = Pref; -DATA.Pref.AutoSave = false; %Run backwards compability test preferencesbackward; @@ -63,31 +53,28 @@ DATA.updatepacslabels; end -% %this part is overwritten if we find a default preferences -% if not(isfield(DATA.Pref,'UserLogging')) -% DATA.Pref.UserLogging = false; -% end; -% -% if not(isfield(DATA.Pref,'UserLogPath')) -% DATA.Pref.UserLogPath = []; -% end; - %Check if we should read in default preferences for PACS, Server etc. -filename = [pwd filesep 'default_preferences.mat']; +filename = [DATA.SegmentFolder filesep 'default_preferences.mat']; if exist(filename,'file') load(filename,'Pref','-mat'); - mydisp('Found default preferences, overriding PACS, DICOM, Server settings, and User logging.'); - mydisp(' '); + disp('Found default preferences, overriding PACS, DICOM, Server settings, and User logging.'); + disp(' '); %Copy data DATA.Pref.Pacs = Pref.Pacs; DATA.Pref.Dicom = Pref.Dicom; - DATA.Pref.Server = Pref.Server; + + if isfield(Pref,'Server') + DATA.Pref.Server = Pref.Server; + end + DATA.Pref.Gensvar = Pref.Gensvar; DATA.Pref.AETitle = Pref.AETitle; DATA.Pref.UseProxyServer = Pref.UseProxyServer; DATA.Pref.ProxySettings = Pref.ProxySettings; - + if isfield(Pref,'UseCache') + DATA.Pref.UseCache = Pref.UseCache; + end if isfield(Pref,'UserLogging') DATA.Pref.UserLogging = Pref.UserLogging; end @@ -98,16 +85,61 @@ %Run extra backwards compability test preferencesbackward; -end; +end + +%Add preferences selected by commandline +commandlinehelper('storetopref'); + +% Create PatientDatabase folders under the pathway saved in Segment +% Preference, executed only through command line flag -UseDefaultStudiesFolder +if isfield(DATA.Pref,'UseDefaultStudiesFolder') && DATA.Pref.UseDefaultStudiesFolder==1 + try + wizardsetup('createdatabasefolders') + catch + mywarning('It was not possible to create Patientdatabase folders under the pathway that was saved in Segment preferences'); + end + DATA.Pref.UseDefaultStudiesFolder=0; %Set to 0 after the command line flag call +end + +%Use ComputerAEtitle instead of that one saved in Segment's Preferences. +%Executed through command line flag -UseComputerAETitle +if isfield(DATA.Pref,'UseComputerAETitle') && DATA.Pref.UseComputerAETitle==1 + + if ~isempty(DATA.Pref.Server.AETitle) + aetitle = getenv('COMPUTERNAME'); + if isempty(aetitle) + aetitle = 'SEGMENT'; + end + if ~strcmp(DATA.Pref.Server.AETitle,aetitle) + DATA.Pref.Server.AETitle = aetitle; + end + end + DATA.Pref.UseComputerAETitle=0; %Set to 0 after the command line flag call +end %Select OpenGL according to preferences if DATA.Pref.OpenGLSoftware - opengl software; + try + opengl software; + catch me + disp('Selecting software openGL not succeccful.'); + mydispexception(me); + end else - opengl hardware; -end; -disp('OpenGL info:'); -opengl info; + try + opengl hardware; + catch me + disp('Selecting hardware openGL not succeccful.'); + mydispexception(me); + end +end +try + disp('OpenGL info:'); + opengl info; +catch me + disp('Showing openGL info not succeccful.'); + mydispexception(me); +end %--------------------------- function preferencesbackward @@ -119,56 +151,81 @@ aetitle = getenv('COMPUTERNAME'); if isempty(aetitle) aetitle = 'SEGMENT'; - end; + end DATA.Pref.AETitle = aetitle; -end; +end %Backwards compability +if ~isfield(DATA.Pref,'Sync') + DATA.Pref.Sync.DatabasePath = []; + DATA.Pref.Sync.Frequency = 2; + DATA.Pref.Sync.LastUpdate = ''; + DATA.Pref.Sync.LimitDate = 1; + DATA.Pref.Sync.AutoDeleteOn = 0; + DATA.Pref.Sync.DeleteOptions = 'date'; + DATA.Pref.Sync.DeleteLimitNumber = '1'; + DATA.Pref.Sync.DeleteMatFiles = 0; + DATA.Pref.Sync.MoveFiles = 0; + DATA.Pref.Sync.MovePath = '\\...'; +elseif ~isfield(DATA.Pref.Sync,'AutoDeleteOn') + DATA.Pref.Sync.AutoDeleteOn = 0; + DATA.Pref.Sync.DeleteOptions = 'date'; + DATA.Pref.Sync.DeleteLimitNumber = '1'; + DATA.Pref.Sync.DeleteMatFiles = 0; + DATA.Pref.Sync.MoveFiles = 0; + DATA.Pref.Sync.MovePath = '\\...'; +end +if ~isfield(DATA.Pref,'AutoLoader') + DATA.Pref.AutoLoader = []; +end +if ~isfield(DATA.Pref,'FavRoiNames') + DATA.Pref.FavRoiNames = []; +end if not(isfield(DATA.Pref,'Pacs')) %These fields can (and have to) be skipped if restruct has been done if not(isfield(DATA.Pref,'AnonymMode')) DATA.Pref.AnonymMode = false; - end; + end if not(isfield(DATA.Pref,'EndoCenter')) DATA.Pref.EndoCenter = true; - end; + end if not(isfield(DATA.Pref,'BlackWhite')) DATA.Pref.BlackWhite = false; - end; + end if not(isfield(DATA.Pref,'LineWidth')) DATA.Pref.LineWidth = 1; - end; + end if not(isfield(DATA.Pref,'NumPoints')) DATA.Pref.NumPoints = 80; - end; + end if not(isfield(DATA.Pref,'RadialProfiles')) DATA.Pref.RadialProfiles = DATA.Pref.NumPoints; DATA.Pref.NumPoints = 80; - end; + end if not(isfield(DATA.Pref,'LearnMode')) DATA.Pref.LearnMode = true; - end; + end if not(isfield(DATA.Pref,'UndoHistory')) DATA.Pref.UndoHistory = 10; - end; + end if not(isfield(DATA.Pref,'IncludeAllPixelsInRoi')) DATA.Pref.IncludeAllPixelsInRoi = false; - end; + end if not(isfield(DATA.Pref,'AutoSave')) - DATA.Pref.AutoSave = true; - end; + DATA.Pref.AutoSave = false; + end if not(isfield(DATA.Pref,'ContourAdjustDistance')) DATA.Pref.ContourAdjustDistance = 2.5; - end; + end if not(isfield(DATA.Pref,'AllowDicomCache')) DATA.Pref.AllowDicomCache = false; %Set to false since obsoleted - end; + end if not(isfield(DATA.Pref,'DoNotAsk')) DATA.Pref.DoNotAsk = false; - end; + end if not(isfield(DATA.Pref,'DICOMPort')) DATA.Pref.DICOMPort = '104'; - end; + end if not(isfield(DATA.Pref,'NormalizePhase')) DATA.Pref.NormalizePhase = []; %EH bugfix: was without .Pref. end @@ -183,9 +240,9 @@ aetitle = getenv('COMPUTERNAME'); if isempty(aetitle) aetitle = 'SEGMENT'; - end; + end DATA.Pref.AETitle = aetitle; - end; + end %added by eriks if not(isfield(DATA.Pref,'UseLight')) @@ -194,15 +251,15 @@ if not(isfield(DATA.Pref,'ViewInterpolated')) DATA.Pref.ViewInterpolated = true; - end; + end if not(isfield(DATA.Pref,'UserLogging')) DATA.Pref.UserLogging = false; - end; + end if not(isfield(DATA.Pref,'UserLogPath')) DATA.Pref.UserLogPath = []; - end; + end %added by EH: if not(isfield(DATA.Pref,'Force16Bit')) @@ -214,31 +271,30 @@ %for multiframe DICOM images if not(isfield(DATA.Pref,'FasterPreview')) DATA.Pref.FasterPreview = true; - end; + end %--- Paths if not(isfield(DATA.Pref,'PacsTempStoragePath')) - DATA.Pref.PacsTempStoragePath = [pwd filesep 'Database' filesep 'TEMP']; - end; + DATA.Pref.PacsTempStoragePath = [DATA.SegmentFolder filesep 'Database' filesep 'TEMP']; + end if not(isfield(DATA.Pref,'DicomPath')) - DATA.Pref.DicomPath = [pwd filesep 'Database' filesep 'DICOM']; - end; + DATA.Pref.DicomPath = [DATA.SegmentFolder filesep 'Database' filesep 'DICOM']; + end if not(isfield(DATA.Pref,'AnalysedPath')) - DATA.Pref.AnalysedPath = [pwd filesep 'Database' filesep 'Analysed']; - end; + DATA.Pref.AnalysedPath = [DATA.SegmentFolder filesep 'Database' filesep 'Analysed']; + end if not(isfield(DATA.Pref,'reportsheetpath')) - DATA.Pref.reportsheetpath = [pwd filesep 'Database' filesep 'Report']; + DATA.Pref.reportsheetpath = [DATA.SegmentFolder filesep 'Database' filesep 'Report']; end if not(isfield(DATA.Pref,'CDPath')) DATA.Pref.CDPath = 'D:'; - end; + end if not(isfield(DATA.Pref,'ImageBasePath')) - DATA.Pref.ImageBasePath = [pwd filesep 'Database']; - end; + DATA.Pref.ImageBasePath = [DATA.SegmentFolder filesep 'Database']; + end if not(isfield(DATA.Pref,'NumInterpPoints')) DATA.Pref.NumInterpPoints = 15; - end; - + end % JT 090929 #411 if not(isfield(DATA.Pref, 'ShowSeriesDescription')) DATA.Pref.ShowSeriesDescription = false; @@ -275,40 +331,51 @@ %EH 110217 if not(isfield(DATA.Pref,'RetrieveOptions')) DATA.Pref.RetrieveOptions = ''; %'--prefer-little --propose-little --bit-preserving'; %This is used for movescu to configure. - end; + end if not(isfield(DATA.Pref,'QueryOptions')) DATA.Pref.QueryOptions = ''; %'--propose-little'; %This is used for findscu to configure. - end; + end if not(isfield(DATA.Pref,'ReceiveOptions')) DATA.Pref.ReceiveOptions = ''; %'--prefer-little'; %This is used for storescp to configure. - end; + end if not(isfield(DATA.Pref,'SendOptions')) DATA.Pref.SendOptions = ''; %This is used for storescu to configure. - end; + end %NL 110426 if not(isfield(DATA.Pref,'FastPreviewLoad')) DATA.Pref.FastPreviewLoad = true; end - %NL 110901 + %NL 110901, KG 210407 if not(isfield(DATA.Pref, 'GensvarUrl')) DATA.Pref.GensvarUrl = 'http://'; DATA.Pref.GensvarUsername = ''; DATA.Pref.GensvarPassword = ''; + DATA.Pref.Gensvarfailedtosend=1; + DATA.Pref.Gensvarsaved=0; end %NL 111011 prefrestruct; end +if not(isfield(DATA.Pref,'UseCache')) + DATA.Pref.UseCache = false; +end +%Backward compability for Server settings +if ~(isfield(DATA.Pref,'Server')) + DATA.Pref.Server.DICOMPort='104'; + DATA.Pref.Server.AETitle=DATA.Pref.AETitle; + DATA.Pref.Server.ReceiveOptions=''; +end if not(isfield(DATA.Pref,'UserLogging')) DATA.Pref.UserLogging = false; -end; +end if not(isfield(DATA.Pref,'UserLogPath')) DATA.Pref.UserLogPath = []; -end; +end %NL111012 if not(isfield(DATA.Pref.Pacs,'patientconfig')) @@ -325,7 +392,7 @@ %NL130311 if not(isfield(DATA.Pref.Pacs,'PAFPathname')) - DATA.Pref.Pacs.PAFPathname = [pwd filesep 'PAF']; + DATA.Pref.Pacs.PAFPathname = [DATA.SegmentFolder filesep 'PAF']; end %NL130925 @@ -338,6 +405,12 @@ DATA.Pref.Language = 'English'; end +if not(isfield(DATA.Pref,'ReportLanguage')) + DATA.Pref.ReportLanguage = 'English'; +end + + + %NL140429 if not(isfield(DATA.Pref,'BackgroundColor')) DATA.Pref.BackgroundColor = false; @@ -359,32 +432,44 @@ useproxyserver(false); %turn off; else useproxyserver(DATA.Pref.UseProxyServer); %turn on/off; -end; +end %Obsoleted => disable DATA.Pref.AllowDicomCache = false; %EH: Set to false since obsoleted if not(isfield(DATA.Pref,'OpenGLSoftware')) DATA.Pref.OpenGLSoftware = false; %Klas: before hardware was default. -end; +end if not(isfield(DATA.Pref,'GUIBackgroundColor')) - DATA.Pref.GUIBackgroundColor = [0.94 0.94 0.94]; -end; + DATA.Pref.GUIBackgroundColor = [0.2118,0.2353,0.2824]; %Dark blue +end if not(isfield(DATA.Pref,'AskAddComment')) DATA.Pref.AskAddComment = true; -end; +end if not(isfield(DATA.Pref,'GPU')) DATA.Pref.GPU = []; - DATA.Pref.GPU.NumGPU = gpuDeviceCount; %number of GPU's available + try + DATA.Pref.GPU.NumGPU = gpuDeviceCount; %number of GPU's available + catch + DATA.Pref.GPU.NumGPU = 0; + end if DATA.Pref.GPU.NumGPU > 0 DATA.Pref.GPU.Use = true; else DATA.Pref.GPU.Use = false; - end; -end; + end +end + +if not(isfield(DATA.Pref,'NoBeep')) + DATA.Pref.NoBeep = false; +end + +if ~isfield(DATA.Pref,'SaveUserInfo') + DATA.Pref.SaveUserInfo = false; +end %-------------------- function prefrestruct @@ -422,6 +507,8 @@ [gensvar,pref] = mvfield(gensvar,pref,'GensvarUrl','Url'); [gensvar,pref] = mvfield(gensvar,pref,'GensvarUsername','Username'); [gensvar,pref] = mvfield(gensvar,pref,'GensvarPassword','Password'); + [gensvar,pref] = mvfield(gensvar,pref,'Gensvarfailedtosend','failedtosend') + [gensvar,pref] = mvfield(gensvar,pref,'Gensvarsaved','saved') pref.Gensvar = gensvar; end @@ -453,12 +540,12 @@ %to compile in segment when compiling segmentserver. pathname = getpreferencespath; -Pref = DATA.Pref; %#ok %Saved to file +Pref = DATA.Pref; %Saved to file try save([pathname filesep '.segment_preferences.mat'],'Pref'); catch %#ok myfailed('Could not save preferences. Write permission? Disk full?',DATA.PrefHandles.fig); return; -end; +end disp('Preferences saved.'); \ No newline at end of file diff --git a/source/logo.png b/source/logo.png new file mode 100644 index 0000000..af9e65a Binary files /dev/null and b/source/logo.png differ diff --git a/source/longaxis.fig b/source/longaxis.fig deleted file mode 100644 index a829ebc..0000000 Binary files a/source/longaxis.fig and /dev/null differ diff --git a/source/longaxisplot.p b/source/longaxisplot.p deleted file mode 100644 index 0068801..0000000 Binary files a/source/longaxisplot.p and /dev/null differ diff --git a/source/longaxistools.m b/source/longaxistools.m index 04b1707..c9dfdcd 100644 --- a/source/longaxistools.m +++ b/source/longaxistools.m @@ -34,9 +34,13 @@ ch4no = find(strcmp({SET.ImageViewPlane},'4CH'),1); if ~isempty(ch4no) && ~isempty(SET(ch4no).(xfield)) seg4tfs = find(~isnan(SET(ch4no).(xfield)(1,:))); - if numel(seg4tfs) < 3 + if ~isempty(seg4tfs) seg4tfs(seg4tfs == SET(ch4no).EST) = 0; seg4tfs(seg4tfs == SET(ch4no).EDT) = -1; + seg4tfs(seg4tfs>0) = []; + if numel(seg4tfs)<2 + seg4tfs = []; + end end else seg4tfs = []; @@ -46,9 +50,13 @@ ch3no = find(strcmp({SET.ImageViewPlane},'3CH'),1); if ~isempty(ch3no) && ~isempty(SET(ch3no).(xfield)) seg3tfs = find(~isnan(SET(ch3no).(xfield)(1,:))); - if numel(seg3tfs) < 3 + if ~isempty(seg3tfs) seg3tfs(seg3tfs == SET(ch3no).EST) = 0; seg3tfs(seg3tfs == SET(ch3no).EDT) = -1; + seg3tfs(seg3tfs>0) = []; + if numel(seg3tfs)<2 + seg3tfs = []; + end end else seg3tfs = []; @@ -56,11 +64,15 @@ end ch2no = find(strcmp({SET.ImageViewPlane},'2CH'),1); - if ~isempty(ch2no) && ~isempty(SET(ch2no).(xfield)); + if ~isempty(ch2no) && ~isempty(SET(ch2no).(xfield)) seg2tfs = find(~isnan(SET(ch2no).(xfield)(1,:))); - if numel(seg2tfs) < 3 + if ~isempty(seg2tfs) seg2tfs(seg2tfs == SET(ch2no).EST) = 0; seg2tfs(seg2tfs == SET(ch2no).EDT) = -1; + seg2tfs(seg2tfs>0) = []; + if numel(seg2tfs)<2 + seg2tfs = []; + end end else seg2tfs = []; @@ -90,6 +102,7 @@ end return end + for tf = setdiff(intersect(seg2tfs,seg3tfs),seg4tfs) [~,didcalc] = calcbiplanevolume_helper([ch2no ch3no],tf,segfield); end @@ -99,6 +112,7 @@ for tf = setdiff(intersect(seg4tfs,seg2tfs),seg3tfs) [~,didcalc] = calcbiplanevolume_helper([ch4no ch2no],tf,segfield); end + end %------------------------------------------------------------------------ @@ -152,6 +166,22 @@ end X = [SET(no).ResolutionX*(SET(no).(xfield)(:,timeframe)-ix(1)) ... SET(no).ResolutionY*(SET(no).(yfield)(:,timeframe)-iy(1))]'; + + %do extra check that a horse shoe is drawn + %extract convhull + inds = convhull(X'); + a1 = calcfunctions('stablepolyarea',X(1,:),X(2,:)); + a2 = calcfunctions('stablepolyarea',X(1,inds),X(2,inds)); + if a2>a1*(1.5) + % jelena: skip calculation for now + volume = nan; + stus = false; + return + %this is likely a horseshoe segmentation + [endoindexes, epiindexes] = splithorseshowsegmentation(X, inds); + X = X(:,endoindexes); + end + ivec = [ix(2)-ix(1);iy(2)-iy(1)]; ivec = ivec/norm(ivec); S = [ivec ([0 1;-1 0]*ivec)]; @@ -189,7 +219,52 @@ end %-------------------------------------- -function showpointinallviews(clickedim) +function [endoindexes, epiindexes] = splithorseshowsegmentation(originalcontour, epiindexes) +% find jumps in indices larger than 10% of the contour length + +minjump = floor(length(originalcontour)/10); +maxjump = length(originalcontour) - 10; +jumps = find (abs(diff(epiindexes)) >= minjump & abs(diff(epiindexes)) <= maxjump); +% loop over all jumps +contourlength = zeros(length(jumps),1); +for loop = 1: length(jumps) + % calculate contour length between points + startindex = epiindexes(jumps(loop)); + endindex = epiindexes(jumps(loop) + 1); + if startindex > endindex + tmp = startindex; + startindex = endindex; + endindex = tmp; + end + x = originalcontour(1,startindex : endindex); + y = originalcontour(2,startindex : endindex); + contourlength(loop) = sum(sqrt(diff(x).^2 + diff(y).^2)); +end +[epilength,index] = max(contourlength); +startindex = epiindexes(jumps(index)); +endindex = epiindexes(jumps(index) + 1); +if startindex > endindex + tmp = startindex; + startindex = endindex; + endindex = tmp; +end +epiindexes = startindex:endindex; +endoindexes = setdiff(1:length(originalcontour),epiindexes); +x = originalcontour(1,endoindexes); +y = originalcontour(2,endoindexes); +endolength = sum(sqrt(diff(x).^2 + diff(y).^2)); + +if endolength > epilength + %switch + tmp = epiindexes; + epiindexes = endoindexes; + endoindexes = tmp; +end + + + +%-------------------------------------- +function showpointinallviews(clickedim) %#ok %-------------------------------------- global DATA SET NO segment_main('normal_Buttondown',clickedim); @@ -226,7 +301,7 @@ function showpointinallviews(clickedim) case 'gla' [xo,yo] = calcfunctions('sax2gla',x,y,z,NO); plot(hloop,yo,xo,'yo'); - case {'one','ortho'} + case {'one','orth'} plot(hloop,y,x,'yo'); otherwise [xofs,yofs] = calcfunctions('calcoffset',z,[],NO); @@ -254,27 +329,6 @@ function showpointinallviews(clickedim) % end -%------------------------------------ -function fourviewspushbutton_Callback -%------------------------------------ -%Setup view matrix of four main cine views -global DATA SET - -saxno = find(strcmp({SET.ImageViewPlane},'Short-axis'),1); -ch4no = find(strcmp({SET.ImageViewPlane},'4CH'),1); -ch3no = find(strcmp({SET.ImageViewPlane},'3CH'),1); -ch2no = find(strcmp({SET.ImageViewPlane},'2CH'),1); - -if saxno && ch4no && ch3no && ch2no - DATA.ViewMatrix = [2 2]; - DATA.ViewIM = {[] [] [] []}; - DATA.ViewPanels = [saxno ch4no ch3no ch2no]; - DATA.ViewPanelsType = {'one','one','one','one'}; -else - myfailed('Could not find all view planes'); -end - -drawfunctions('drawall'); %----------------------------------- function cros = dointersect(no1,no2) diff --git a/source/lv.p b/source/lv.p index af5aabf..61b477f 100644 Binary files a/source/lv.p and b/source/lv.p differ diff --git a/source/lvpeter.p b/source/lvpeter.p index 5691332..bc16349 100644 Binary files a/source/lvpeter.p and b/source/lvpeter.p differ diff --git a/source/lvsegmentation.fig b/source/lvsegmentation.fig index 1324500..ffcf1db 100644 Binary files a/source/lvsegmentation.fig and b/source/lvsegmentation.fig differ diff --git a/source/lvsegmentation.m b/source/lvsegmentation.m deleted file mode 100644 index fff37a0..0000000 --- a/source/lvsegmentation.m +++ /dev/null @@ -1,818 +0,0 @@ -function varargout = lvsegmentation(varargin) -% LVSEGMENTATION MATLAB code for lvsegmentation.fig - -macro_helper(varargin{:}); -if nargin < 1 || isempty(varargin{1}) - varargin{1} = 'init'; -end - -[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard - -%------------ -function init -%------------ -%Initialize the GUI - -global DATA SET NO - -%cineno = findfunctions('findno'); -%saxno = find(strcmp({SET.ImageViewPlane},'Short-axis')); -%zno = find([SET.ZSize] > 1); -% saxno = intersect(cineno,union(saxno,zno)); -% -% if isempty(saxno) -% if ismember(NO,zno) && ... -% yesno('Could not find image stack defined as Short-axis Cine. Use current stack?'); -% saxno = NO; -% SET(saxno).ImageViewPlane = 'Short-axis'; -% SET(saxno).ImageType = 'Cine'; -% drawfunctions('updatenopanels',saxno); -% else -% myfailed('Could not find short-axis image stack'); -% return -% end -% end -% -% if ismember(NO,saxno) -% saxno = NO; -% else -% nos = cellfun(@(x)dprintf('Short-axis stack %d',x), ... -% num2cell(saxno),'UniformOutput',false); -% m = mymenu('Do segmentation on short-axis stack?', ... -% nos{:}); -% if m -% saxno = saxno(m); -% else -% return; -% end -% end - - -[saxno,ch2no,ch3no,ch4no,success]=croplvall(1); - -if ~success - return -end - -if SET(saxno).ZSize < 5 - myfailed('Need at least 5 slices for fully automated segmentation (endo&epi).',DATA.GUI.Segment); - return -end - -%Open LV wizard GUI -gui = mygui('lvsegmentation.fig'); -DATA.GUI.LVSegmentation = gui; - -gui.saxno = saxno; -gui.ch4no = ch4no; -gui.ch3no = ch3no; -gui.ch2no = ch2no; - -%set ED as current time frame -tools('enddiastole_Callback'); - -%Init time slider -gui.tf = SET(gui.saxno).CurrentTimeFrame; -tsz = SET(gui.saxno).TSize; -if tsz == 1 - set(gui.handles.timebaraxes,'visible','off'); -else - sliderstep = [1/(tsz-1) 5/(tsz-1)]; - set(gui.handles.timeslider,'Min',1,'Max',tsz,'Value',gui.tf, ... - 'SliderStep',sliderstep); - set(gui.handles.timetext,'String',sprintf('%0.0f ms',1000*SET(gui.saxno).TimeVector(gui.tf))); - - load Icons.mat - set(gui.handles.prevpushbutton,'CData',icon.prev); - set(gui.handles.playtogglebutton,'CData',icon.play); - set(gui.handles.nextpushbutton,'CData',icon.next); - inittimebar; -end - -%find lv center -if isempty(SET(gui.saxno).StartSlice) || isempty(SET(gui.saxno).EndSlice) - SET(gui.saxno).StartSlice = round(SET(gui.saxno).ZSize); - SET(gui.saxno).EndSlice = round(SET(gui.saxno).ZSize); -end -if SET(gui.saxno).EndSlice - SET(gui.saxno).StartSlice < 4 - SET(gui.saxno).EndSlice = min([SET(gui.saxno).ZSize ceil(SET(gui.saxno).ZSize*3/4)]); - SET(gui.saxno).StartSlice = max([1 floor(SET(gui.saxno).ZSize/4)]); -end -gui.midslice = floor((SET(gui.saxno).StartSlice + SET(gui.saxno).EndSlice)/2); -[x,y] = findfunctions('findlvcenter',gui.saxno,SET(gui.saxno).StartSlice:SET(gui.saxno).EndSlice); -SET(gui.saxno).CenterX=x; -SET(gui.saxno).CenterY=y; - -[rows,cols] = calcfunctions('calcrowscols',gui.saxno); -gui.matrix = [rows cols]; %viewmatrix for shortaxis image - -gui.saxim = calcfunctions('calcmontageviewim',gui.saxno,gui.matrix); -gui.midim = calcfunctions('remapuint8',SET(gui.saxno).IM(:,:,:,gui.midslice),gui.saxno); -emptyim = uint8(zeros(1,1,SET(gui.saxno).TSize)); -gui.ch4im = emptyim; -gui.ch3im = emptyim; -gui.ch2im = emptyim; -if ~isempty(gui.ch4no) - tfs = round(linspace(1,SET(gui.ch4no).TSize,SET(gui.saxno).TSize)); - gui.ch4im = calcfunctions('remapuint8',SET(gui.ch4no).IM(:,:,tfs),gui.ch4no); -end -if ~isempty(gui.ch3no) - tfs = round(linspace(1,SET(gui.ch3no).TSize,SET(gui.saxno).TSize)); - gui.ch3im = calcfunctions('remapuint8',SET(gui.ch3no).IM(:,:,tfs),gui.ch3no); -end -if ~isempty(gui.ch2no) - tfs = round(linspace(1,SET(gui.ch2no).TSize,SET(gui.saxno).TSize)); - gui.ch2im = calcfunctions('remapuint8',SET(gui.ch2no).IM(:,:,tfs),gui.ch2no); -end - -%plot sax image stack -gui.handles.saximh = image(gui.saxim(:,:,gui.tf),'Parent',gui.handles.shortaxisaxes); -gui.handles.midimh = image(gui.midim(:,:,gui.tf),'Parent',gui.handles.midsliceaxes); - -axh = [gui.handles.shortaxisaxes gui.handles.midsliceaxes ... - gui.handles.ch4axes gui.handles.ch3axes gui.handles.ch2axes]; -colormap(axh(1),gray(255)); -colormap(axh(2),gray(255)); -hold(axh(1),'on'); -hold(axh(2),'on'); -set(gui.handles.saximh,'ButtonDownFcn', ... - 'lvsegmentation(''shortaxisaxes_Buttondown'')'); -set(gui.handles.midimh,'ButtonDownFcn', ... - 'lvsegmentation(''midsliceaxes_Buttondown'')'); - -%plot long-axis image stacks -if ~isempty(gui.ch4no) -gui.handles.ch4imh = image(gui.ch4im(:,:,gui.tf),'Parent',gui.handles.ch4axes); -colormap(axh(3),gray(255)); -hold(axh(3),'on'); -set(gui.handles.ch4imh,'ButtonDownFcn', ... - 'lvsegmentation(''ch4axes_Buttondown'')'); -else - set(gui.handles.ch4axes,'visible','off'); -end -if ~isempty(gui.ch3no) -gui.handles.ch3imh = image(gui.ch3im(:,:,gui.tf),'Parent',gui.handles.ch3axes); -colormap(axh(4),gray(255)); -hold(axh(4),'on'); -set(gui.handles.ch3imh,'ButtonDownFcn', ... - 'lvsegmentation(''ch3axes_Buttondown'')'); -else - set(gui.handles.ch3axes,'visible','off'); -end -if ~isempty(gui.ch2no) -gui.handles.ch2imh = image(gui.ch2im(:,:,gui.tf),'Parent',gui.handles.ch2axes); -colormap(axh(5),gray(255)); -hold(axh(5),'on'); -set(gui.handles.ch2imh,'ButtonDownFcn', ... - 'lvsegmentation(''ch2axes_Buttondown'')'); -else - set(gui.handles.ch2axes,'visible','off'); -end - -axis(axh,'off'); -axis(axh,'equal'); - -%Initiate plot handles -gui.handles.startsliceframe = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.endsliceframe = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.startslice4ch = plot(gui.handles.ch4axes,[],[]); -gui.handles.endslice4ch = plot(gui.handles.ch4axes,[],[]); -gui.handles.startslice3ch = plot(gui.handles.ch3axes,[],[]); -gui.handles.endslice3ch = plot(gui.handles.ch3axes,[],[]); -gui.handles.startslice2ch = plot(gui.handles.ch2axes,[],[]); -gui.handles.endslice2ch = plot(gui.handles.ch2axes,[],[]); -gui.handles.center = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.centermid = plot(gui.handles.midsliceaxes,[],[]); -gui.handles.center4ch = plot(gui.handles.ch4axes,[],[]); -gui.handles.center3ch = plot(gui.handles.ch3axes,[],[]); -gui.handles.center2ch = plot(gui.handles.ch2axes,[],[]); - -set(gui.fig,'KeyPressFcn', ... - @(hObject,eventdata)lvsegmentation('keypressed',hObject,eventdata)); - -updateselectedslices; -updatecenterpoint; - -%------------------------------------- -function [saxno,ch2no,ch3no,ch4no,success]=croplvall(assertboundaries,saxno) -%--------------------------------- -global SET DATA NO -%Assume succes -success = 1; - -if nargin==0 -assertboundaries=0; -end - -ch2no = []; -ch3no = []; -ch4no = []; - -cineno = findfunctions('findno'); -saxno = find(strcmp({SET.ImageViewPlane},'Short-axis')); -zno = find([SET.ZSize] > 1); -saxno = intersect(cineno,union(saxno,zno)); - -if isempty(saxno) - if ismember(NO,zno) && ... - yesno('Could not find image stack defined as Short-axis Cine. Use current stack?'); - saxno = NO; - SET(saxno).ImageViewPlane = 'Short-axis'; - SET(saxno).ImageType = 'Cine'; - drawfunctions('updatenopanels',saxno); - else - myfailed('Could not find short-axis image stack'); - success=0; - return - end -end - -%if called from lv segmentation short axis stack selection has already been done. - - if ismember(NO,saxno) - saxno = NO; - else - nos = cellfun(@(x)dprintf('Short-axis stack %d',x), ... - num2cell(saxno),'UniformOutput',false); - if ~assertboundaries - m = mymenu('Do crop on short-axis stack?', ... - nos{:}); - else - m = mymenu('Do segmentation on short-axis stack?', ... - nos{:}); - end - if m - saxno = saxno(m); - else - success=0; - return; - end - end - - -nostocrop = []; - -% sz = zeros(size(saxno)); -% %then use biggest -% if length(saxno)>1 -% for i=1:length(saxno) -% no=saxno(i); -% sz(i) = SET(no).XSize * SET(no).ResolutionX * SET(no).YSize * SET(no).ResolutionY; -% end -% [~,ind]=max(sz); -% saxno=saxno(ind); -% end - -%only if assert boundaries can be done smarter but this always works -if assertboundaries - if SET(saxno).XSize * SET(saxno).ResolutionX > 210 || ... - SET(saxno).YSize * SET(saxno).ResolutionY > 210 - nostocrop = saxno; - end -else - nostocrop = saxno; -end - -for cham = 2:4 - chno = find(strcmp({SET(:).ImageViewPlane},sprintf('%dCH',cham))); - if ~isempty(chno) - if length(chno) > 1 - cinechno = find(strcmp({SET(cineno).ImageViewPlane},sprintf('%dCH',cham))); - if ~isempty(cinechno) && length(cinechno) == 1 - chno = cineno(cinechno); - else - %ask user - nostri = '('; - for loop = 1:length(chno) - if loop == length(chno) - nostri = [nostri sprintf('%d)',chno(loop))]; - else - nostri = [nostri sprintf('%d, ',chno(loop))]; - end - end - uniquechno = inputdlg({dprintf('Select %dCH image stack out of %s.',cham,nostri)},'Image Stack',1,{sprintf('%d',chno(1))}); - if ~ismember(str2num(uniquechno{1}),chno) - uniquechno = []; - end - if isempty(uniquechno) - myfailed('Invalid image stack.',DATA.GUI.Segment); - success=0; - return; - else - [chno,ok] = str2num(uniquechno{1}); %#ok - if not(ok) - myfailed('Invalid image stack.',DATA.GUI.Segment); - success=0; - return; - end; - end; - end - end - if cham == 2 - ch2no = chno; - elseif cham == 3 - ch3no = chno; - elseif cham == 4 - ch4no = chno; - end - %Check if image needs cropping only if assert boundaries - if assertboundaries - if SET(chno).XSize * SET(chno).ResolutionX > 260 || ... - SET(chno).YSize * SET(chno).ResolutionY > 260 - nostocrop = [nostocrop chno]; %#ok - end - else - nostocrop = [nostocrop chno]; - end - end -end - - -if assertboundaries - if ~isempty(nostocrop) - if ~autocropall(true,nostocrop) - if ismember(saxno,nostocrop) - myfailed('Need to crop short-axis stack in order to do LV segmentation'); - success=0; - return - end - elseif SET(saxno).XSize * SET(saxno).ResolutionX > 250 || ... - SET(saxno).YSize * SET(saxno).ResolutionY > 250 - myfailed('Need to crop short-axis stack more in order to do LV segmentation'); - autocropall(true,nostocrop) - if SET(saxno).XSize * SET(saxno).ResolutionX > 250 || ... - SET(saxno).YSize * SET(saxno).ResolutionY > 250 - myfailed('Need to crop short-axis stack more in order to do LV segmentation'); - success=0; - return - end - end - end -else - autocropall(true,nostocrop) -end - -%------------------- -function inittimebar -%------------------- -%Initiate timebar axis -global DATA SET -gui = DATA.GUI.LVSegmentation; - -h = gui.handles.timebaraxes; -no = gui.saxno; -if isempty(no) - return -end -set(h,'ButtonDownFcn', ... - @(hObject,eventdata)lvsegmentation('timebaraxes_ButtonDownFcn',hObject,eventdata)); - -delete(get(h,'Children')); - -tvec = SET(no).TimeVector; - -hold(h,'on'); -fcn = @(hObject,eventdata)lvsegmentation('timebar_ButtonDownFcn',hObject,eventdata); - -%Draw timebar (red) and set its buttondown fcn -gui.handles.timebar = plot(h,tvec(gui.tf)*[1 1],[0 1],'b','Tag','currenttime'); -set(gui.handles.timebar,'ButtonDownFcn',fcn); - -%Set axes options -tvec = SET(no).TimeVector; -tmin = tvec(1); -tmax = tvec(end); - -marg = (tmax-tmin)/500; -axis(h,[tmin-marg tmax+marg 0 1]); -%tstep = 5*(tmax-tmin)/(numel(tvec)-1); -%tickvec = [ceil(tmin/tstep)*tstep:tstep:floor(tmax/tstep)*tstep]; -%tickvec = tvec(1:5:end); -tickvec = tmin:0.2:tmax; -set(h, 'XTick', tickvec,'YTick',[],'XMinorTick','off','XGrid','on', ... - 'XTickLabel',cellfun(@num2str,num2cell(1000*tickvec), ... - 'UniformOutput',false),'TickLength',[0.005 0.025]); - -temp = get(gui.handles.timebaraxes,'ylim'); -ttemp = [tvec;tvec]; -temp = [repmat(temp(1),size(tvec));repmat(temp(1)+0.1*(temp(2)-temp(1)),size(tvec))]; -plot(gui.handles.timebaraxes,ttemp,temp,'k-'); - -updatetimebar; - -%--------------------- -function updatetimebar -%--------------------- -%Update timebar axis -global DATA SET -gui = DATA.GUI.LVSegmentation; - -h = gui.handles.timebaraxes; -no = gui.saxno; -if isempty(no) - return -end - -fcn = get(h,'ButtonDownFcn'); -currenttime = SET(gui.saxno).TimeVector(gui.tf); - -%Update timebar -set(gui.handles.timebar,'XData',currenttime*[1 1]) - -set(h,'ButtonDownFcn',fcn); - - -%--------------------------------------------- -function timebaraxes_ButtonDownFcn(hObject, ~) -%--------------------------------------------- -%Buttondown function for timebar axes. Changes current timeframe to the -%one closest to position of clicked point -global DATA SET -gui = DATA.GUI.LVSegmentation; -no = gui.saxno; -x = mygetcurrentpoint(hObject); -[~,tf] = min(abs(SET(no).TimeVector-x)); -gui.tf = max(min(tf,SET(no).TSize),1); -updateimages; - -%----------------------------------------- -function timebar_ButtonDownFcn(hObject, ~) -%----------------------------------------- -%Buttondown function for graphical timebar object. Activates dragging of timebars. -global DATA -gui = DATA.GUI.LVSegmentation; -no = gui.saxno; -obj = hObject; -motionfcn = @(hObject,eventdata)lvsegmentation('timebaraxes_MotionFcn',hObject,eventdata,obj,no); -set(gui.fig,'WindowButtonMotionFcn',motionfcn); -buttonupfcn = @(hObject,eventdata)lvsegmentation('timebaraxes_ButtonUpFcn',hObject,eventdata); -set(gui.fig,'WindowButtonUpFcn', buttonupfcn); - -%---------------------------------------------- -function timebaraxes_MotionFcn(~, ~, tbobj, no) -%---------------------------------------------- -%Mouse motion function for timebar axes of image specified by input -%parameter 'field'. Used for dragging timebars to change current -%timeframe or start/end points of timeframes in which to align images. -global DATA SET -x = mygetcurrentpoint(get(tbobj,'Parent')); -[~,tf] = min(abs(SET(no).TimeVector-x)); -DATA.GUI.LVSegmentation.tf = max(min(tf,SET(no).TSize),1); -updateimages; - -%------------------------------------------- -function timebaraxes_ButtonUpFcn(hObject, ~) -%------------------------------------------- -%Buttonup function for timebar axes of image specified by input -%parameter 'field'. Deactivates dragging of timebar. -set(hObject,'WindowButtonMotionFcn',[],'WindowButtonUpFcn',[]); - - -%--------------------------- -function timeslider_Callback -%--------------------------- -%Callback for timeslider -global DATA -gui = DATA.GUI.LVSegmentation; - -%Update timeframe and images -gui.tf = round(mygetvalue(gui.handles.timeslider)); -set(gui.handles.timeslider,'Value',gui.tf); -updateimages; - -%-------------------- -function updateimages -%-------------------- -%Update all image stacks and also timebar -global DATA SET -gui = DATA.GUI.LVSegmentation; -set(gui.handles.saximh,'CData',gui.saxim(:,:,gui.tf)); -set(gui.handles.midimh,'CData',gui.midim(:,:,gui.tf)); -if isfield(gui.handles,'ch4imh') - set(gui.handles.ch4imh,'CData',gui.ch4im(:,:,gui.tf)); -end -if isfield(gui.handles,'ch3imh') - set(gui.handles.ch3imh,'CData',gui.ch3im(:,:,gui.tf)); -end -if isfield(gui.handles,'ch2imh') - set(gui.handles.ch2imh,'CData',gui.ch2im(:,:,gui.tf)); -end -set(gui.handles.timetext,'String', ... - sprintf('%0.0f ms',1000*SET(gui.saxno).TimeVector(gui.tf))); -if SET(gui.saxno).TSize > 1 - updatetimebar; -end - -%--------------------- -function prev_Callback -%--------------------- -%Callback for previous timeframe pushbutton -global DATA SET -gui = DATA.GUI.LVSegmentation; -gui.tf = mod(gui.tf-2,SET(gui.saxno).TSize)+1; -updateimages; - -%--------------------- -function next_Callback -%--------------------- -%Callback for next timeframe pushbutton -global DATA SET -gui = DATA.GUI.LVSegmentation; -gui.tf = mod(gui.tf,SET(gui.saxno).TSize)+1; -updateimages; - -%--------------------- -function play_Callback -%--------------------- -%Callback for play togglebutton -global DATA SET -gui = DATA.GUI.LVSegmentation; - -h = gui.handles.playtogglebutton; -no = gui.saxno; -while ishandle(h) && mygetvalue(h) - gui.tf = mod(gui.tf,SET(no).TSize)+1; - set(gui.handles.timeslider,'Value',gui.tf); - updateimages; - %Do pause to release CPU burden. - pause(0.5*SET(no).BeatTime/SET(no).TSize); -end - -%---------------------------- -function updateselectedslices -%---------------------------- -%Draw markers around selected slices -global DATA SET -gui = DATA.GUI.LVSegmentation; - -%Clean up before drawing new frames and lines -delete([gui.handles.startsliceframe gui.handles.endsliceframe ... - gui.handles.startslice4ch gui.handles.endslice4ch ... - gui.handles.startslice3ch gui.handles.endslice3ch ... - gui.handles.startslice2ch gui.handles.endslice2ch]); - -%circlex = cos(linspace(0,2*pi,100))*2*SET(gui.saxno).XSize/gui.matrix(1); -%circley = sin(linspace(0,2*pi,100))*2*SET(gui.saxno).YSize/gui.matrix(2); -if (SET(gui.saxno).XSize*gui.matrix(1)) < (SET(gui.saxno).YSize*gui.matrix(2)) - scalefactorx = 1;%(SET(gui.saxno).XSize*gui.matrix(1))/(SET(gui.saxno).YSize*gui.matrix(2)); - scalefactory = 1; -else - scalefactorx = 1; - scalefactory = 1;%(SET(gui.saxno).YSize*gui.matrix(2))/(SET(gui.saxno).XSize*gui.matrix(1)); -end -boxx = scalefactorx*[-1 -1 1 1 -1]*SET(gui.saxno).XSize/2+0.5*[1 1 -1 -1 1];%gui.matrix(1); -boxy = scalefactory*[-1 1 1 -1 -1]*SET(gui.saxno).YSize/2+0.5*[1 -1 -1 1 1];%gui.matrix(2); -for slice = unique([SET(gui.saxno).StartSlice SET(gui.saxno).EndSlice]) - row = ceil(slice/gui.matrix(2)); - col = slice-(row-1)*gui.matrix(2); - centerx = (row-0.5)*SET(gui.saxno).XSize+0.5;%;%+1;% - centery = (col-0.5)*SET(gui.saxno).YSize+0.5;%;%+1;% - if slice == SET(gui.saxno).StartSlice - gui.handles.startsliceframe = plot( ... - gui.handles.shortaxisaxes,centery+boxy,centerx+boxx,'b','LineWidth',2); - end - if slice == SET(gui.saxno).EndSlice - gui.handles.endsliceframe = plot( ... - gui.handles.shortaxisaxes,centery+boxy,centerx+boxx,'r','LineWidth',2); - end -end -newmid = floor((SET(gui.saxno).StartSlice + SET(gui.saxno).EndSlice)/2); -if newmid ~= gui.midslice - gui.midslice = newmid; - gui.midim = calcfunctions('remapuint8',SET(gui.saxno).IM(:,:,:,gui.midslice)); - set(gui.handles.midimh,'Cdata',gui.midim(:,:,gui.tf)); -end - -if ~isempty(gui.ch4no) - [ssx,ssy] = calcfunctions('calcplaneintersections', ... - gui.ch4no,gui.saxno,'one','one',SET(gui.saxno).StartSlice); - [esx,esy] = calcfunctions('calcplaneintersections', ... - gui.ch4no,gui.saxno,'one','one',SET(gui.saxno).EndSlice); - gui.handles.startslice4ch = plot( ... - gui.handles.ch4axes,ssy,ssx,'b'); - gui.handles.endslice4ch = plot( ... - gui.handles.ch4axes,esy,esx,'r'); -end - -if ~isempty(gui.ch3no) - [ssx,ssy] = calcfunctions('calcplaneintersections', ... - gui.ch3no,gui.saxno,'one','one',SET(gui.saxno).StartSlice); - [esx,esy] = calcfunctions('calcplaneintersections', ... - gui.ch3no,gui.saxno,'one','one',SET(gui.saxno).EndSlice); - gui.handles.startslice3ch = plot( ... - gui.handles.ch3axes,ssy,ssx,'b'); - gui.handles.endslice3ch = plot( ... - gui.handles.ch3axes,esy,esx,'r'); -end - -if ~isempty(gui.ch2no) - [ssx,ssy] = calcfunctions('calcplaneintersections', ... - gui.ch2no,gui.saxno,'one','one',SET(gui.saxno).StartSlice); - [esx,esy] = calcfunctions('calcplaneintersections', ... - gui.ch2no,gui.saxno,'one','one',SET(gui.saxno).EndSlice); - gui.handles.startslice2ch = plot( ... - gui.handles.ch2axes,ssy,ssx,'b'); - gui.handles.endslice2ch = plot( ... - gui.handles.ch2axes,esy,esx,'r'); -end - -segment('updateselectedslices'); - - -%------------------------------ -function recalculatecenterpoint -%------------------------------ -%Recalculate center ponit based on new LV slices - -global SET DATA -gui = DATA.GUI.LVSegmentation; -[x,y] = findfunctions('findlvcenter',gui.saxno,SET(gui.saxno).StartSlice:SET(gui.saxno).EndSlice); -SET(gui.saxno).CenterX=x; -SET(gui.saxno).CenterY=y; - - -%------------------------- -function updatecenterpoint -%------------------------- -%Update center point -global DATA SET -gui = DATA.GUI.LVSegmentation; - -%Clean up before drawing -delete([gui.handles.center gui.handles.centermid ... - gui.handles.center4ch gui.handles.center3ch gui.handles.center2ch]); - -startxyz = [SET(gui.saxno).CenterX; ... - SET(gui.saxno).CenterY; ... - SET(gui.saxno).StartSlice]; -endxyz = [startxyz(1:2); SET(gui.saxno).EndSlice]; - -crosscolor = [1 0.6 0.2]; %DATA.centercrossdef -[tempx,tempy] = ndgrid(0:(gui.matrix(1)-1),0:(gui.matrix(2)-1)); -gui.handles.center = plot(... - gui.handles.shortaxisaxes,... - startxyz(2)+tempy(:)*SET(gui.saxno).YSize,... - startxyz(1)+tempx(:)*SET(gui.saxno).XSize,'+',... - 'color',crosscolor); -gui.handles.centermid = plot( ... - gui.handles.midsliceaxes,startxyz(2),startxyz(1),'+','Color',crosscolor); - -%Get center point coordinates in longaxis images -[saxpos,saxmat] = calcfunctions('calcormat',gui.saxno); -truecenter = [saxpos saxpos] + saxmat*([startxyz endxyz]-1); - -if ~isempty(gui.ch4no) - [ch4pos,ch4mat] = calcfunctions('calcormat',gui.ch4no); - ch4center = 1 + ch4mat\(truecenter - [ch4pos ch4pos]); - gui.handles.center4ch = plot( ... - gui.handles.ch4axes,ch4center(2,:),ch4center(1,:),'Color',crosscolor); -end - -if ~isempty(gui.ch3no) - [ch3pos,ch3mat] = calcfunctions('calcormat',gui.ch3no); - ch3center = 1 + ch3mat\(truecenter - [ch3pos ch3pos]); - gui.handles.center3ch = plot( ... - gui.handles.ch3axes,ch3center(2,:),ch3center(1,:),'Color',crosscolor); -end - -if ~isempty(gui.ch2no) - [ch2pos,ch2mat] = calcfunctions('calcormat',gui.ch2no); - ch2center = 1 + ch2mat\(truecenter - [ch2pos ch2pos]); - gui.handles.center2ch = plot( ... - gui.handles.ch2axes,ch2center(2,:),ch2center(1,:),'Color',crosscolor); -end - -%-------------------------------- -function shortaxisaxes_Buttondown %#ok -%-------------------------------- -global DATA SET -gui = DATA.GUI.LVSegmentation; - -%Extract coordinates clicked -[y,x] = mygetcurrentpoint(gui.handles.shortaxisaxes); -%Find slice -col = 1+floor((y-0.5)/SET(gui.saxno).YSize); -row = 1+floor((x-0.5)/SET(gui.saxno).XSize); -slice = col+(row-1)*gui.matrix(2); - -if slice > SET(gui.saxno).ZSize - return; -end -switch get(gui.fig,'SelectionType') - case 'normal' - if slice <= SET(gui.saxno).EndSlice - SET(gui.saxno).StartSlice = slice; - end - case 'alt' - if slice >= SET(gui.saxno).StartSlice - SET(gui.saxno).EndSlice = slice; - end -end -updateselectedslices; -recalculatecenterpoint; -updatecenterpoint; - -%------------------------------- -function midsliceaxes_Buttondown -%------------------------------- -%Button down function for mid slice axes. Move center point. -global DATA SET -gui = DATA.GUI.LVSegmentation; - -[y,x] = mygetcurrentpoint(gui.handles.midsliceaxes); -SET(gui.saxno).CenterX = x; -SET(gui.saxno).CenterY = y; -updatecenterpoint; - -%-------------------------- -function ch4axes_Buttondown -%-------------------------- - - - -%-------------------------- -function ch3axes_Buttondown -%-------------------------- - - - -%-------------------------- -function ch2axes_Buttondown -%-------------------------- - -%------------------------------------- -function keypressed(hObject,eventdata) -%------------------------------------- -%Keypress function for GUI -global DATA SET -gui = DATA.GUI.LVSegmentation; - -switch eventdata.Key - case 'uparrow' - if isempty(eventdata.Modifier) - SET(gui.saxno).StartSlice = max(1,SET(gui.saxno).StartSlice-1); - else - SET(gui.saxno).EndSlice = max(SET(gui.saxno).StartSlice,SET(gui.saxno).EndSlice-1); - end - updateselectedslices; - recalculatecenterpoint; - updatecenterpoint; - case 'downarrow' - if isempty(eventdata.Modifier) - SET(gui.saxno).StartSlice = min(SET(gui.saxno).EndSlice,SET(gui.saxno).StartSlice+1); - else - SET(gui.saxno).EndSlice = min(SET(gui.saxno).ZSize,SET(gui.saxno).EndSlice+1); - end - updateselectedslices; - recalculatecenterpoint; - updatecenterpoint; - case 'leftarrow' - prev_Callback; - case 'rightarrow' - next_Callback; - case 'p' - set(gui.handles.playtogglebutton,'value',1-mygetvalue(gui.handles.playtogglebutton)); - play_Callback; - case 'd' - if get(gui.handles.playtogglebutton,'value') - set(gui.handles.playtogglebutton,'value',0) - play_Callback; - end - gui.tf = SET(gui.saxno).EDT; - updateimages; - case 's' - if get(gui.handles.playtogglebutton,'value') - set(gui.handles.playtogglebutton,'value',0) - play_Callback; - end - gui.tf = SET(gui.saxno).EST; - updateimages; -end - -%--------------------- -function dolv_Callback %#ok -%--------------------- -%Do LV segmentation in selected slices -global DATA -gui = DATA.GUI.LVSegmentation; -segment('switchtoimagestack',gui.saxno); -oldpol=DATA.ThisFrameOnly; -DATA.ThisFrameOnly=0;%segment('framemode_Callback',2);%segment('thisframeonly_Callback',false); -lvpeter('segmentfullyautomatic_Callback'); -close_Callback -drawfunctions('drawall',DATA.ViewMatrix(1),DATA.ViewMatrix(2)); -figure(DATA.GUI.Segment.fig); -DATA.ThisFrameOnly=oldpol; - -%---------------------- -function close_Callback -%---------------------- -%Close LV segmentation GUI -global DATA - -try - DATA.GUI.LVSegmentation = close(DATA.GUI.LVSegmentation); -catch %#ok - DATA.GUI.LVSegmentation=[]; - delete(gcbf); -end \ No newline at end of file diff --git a/source/lvsegmentation.p b/source/lvsegmentation.p new file mode 100644 index 0000000..e35cb10 Binary files /dev/null and b/source/lvsegmentation.p differ diff --git a/source/lvsegmentationml.fig b/source/lvsegmentationml.fig new file mode 100644 index 0000000..532ef2a Binary files /dev/null and b/source/lvsegmentationml.fig differ diff --git a/source/lvsegmentationml.p b/source/lvsegmentationml.p new file mode 100644 index 0000000..dab2ef9 Binary files /dev/null and b/source/lvsegmentationml.p differ diff --git a/source/macro_helper.m b/source/macro_helper.m index ee3e3ff..c3eee3c 100644 --- a/source/macro_helper.m +++ b/source/macro_helper.m @@ -31,7 +31,7 @@ function macro_helper(varargin) mydisp('--- Starting macro recording ---'); return; - end; + end %stop clause if isequal(varargin{1},'_stop') @@ -41,10 +41,10 @@ function macro_helper(varargin) if isequal(outfid,-1) myfailed('Could not open macro file for writing.'); return; - end; + end for loop=1:(DATA.MacroN-1) fprintf(outfid,'%s\n',DATA.Macro{loop}); - end; + end fprintf(outfid,'%% Ending\n'); fclose(outfid); @@ -53,30 +53,30 @@ function macro_helper(varargin) DATA.Macro = []; DATA.MacroN = 0; return; - end; + end if isequal(varargin{1},'put') if DATA.RecordMacro DATA.Macro{DATA.MacroN} = varargin{2}; DATA.MacroN = DATA.MacroN+1; return; - end; - end; + end + end if isequal(varargin{1},'switchorder') if DATA.RecordMacro switchorder; - end; - end; -end; + end + end +end try if isempty(DATA) || ~DATA.RecordMacro return; %done - end; + end catch return -end; +end st = dbstack; @@ -93,17 +93,21 @@ function macro_helper(varargin) tempstri = ['[' sprintf('%d ',size(varargin{loop})) ']']; else tempstri = sprintf('%0.5g',varargin{loop}); - end; - end; + end + end if loop>2 stri = [stri ',' tempstri]; %#ok else stri = tempstri; - end; + end - end; + end + if isempty(DATA.MacroN) + DATA.MacroN = 1; + end + switch nargin case 0 DATA.Macro{DATA.MacroN} = removeext(st(2).file); @@ -114,7 +118,7 @@ function macro_helper(varargin) otherwise DATA.Macro{DATA.MacroN} = sprintf('%s(''%s'',''%s'');',removeext(st(2).file),fname,stri); DATA.MacroN = DATA.MacroN+1; - end; + end %For handles h = gco; @@ -133,12 +137,12 @@ function macro_helper(varargin) DATA.Macro{DATA.MacroN} = sprintf('%%%s set to value %d\n',tag,v); switchorder; DATA.MacroN = DATA.MacroN+1; - end; + end otherwise - end; - end; + end + end -end; +end %------------------------------ function stri = removeext(stri) @@ -154,7 +158,7 @@ function macro_helper(varargin) if DATA.MacroN<3 myfailed('Cannot switch place on top element.'); -end; +end temp = DATA.Macro{DATA.MacroN-2}; DATA.Macro{DATA.MacroN-2} = DATA.Macro{DATA.MacroN-1}; diff --git a/source/maingui.m b/source/maingui.m deleted file mode 100644 index 17ee6b2..0000000 --- a/source/maingui.m +++ /dev/null @@ -1,6172 +0,0 @@ -classdef maingui < handle %Handle class - - properties - LogFile = []; - UserFile = []; - ProgramVersion = []; - ProgramName = 'Segment'; - ProgramFolderName = 'Segment'; - fig = []; - BlockingFigs = []; - imagefig = []; - DataLoaded = 0; - Locked = 0; - Silent = 0; - Handles = []; - - Interactionlock = false; - Undo = []; %length(SET)*g.Pref.UndoHistory - UndoN = []; - LastSaved = now; - Volrend = false; - ViewPanels = []; - ViewPanelsType = {}; - ViewPanelsMatrix = {}; - ViewIM = {}; - ViewMatrix = []; - LastView = []; - - CurrentPanel = 1; - CurrentTool = 'select'; - CurrentTheme = 'lv'; - Tools = []; - - SegmentFolder = pwd; - - imagedescriptionfile = 'imagedescription.txt'; - manualfile = 'manual.pdf'; - IFUfile = ''; - - GUI = []; - GUISettings = []; - GUIPositions = []; - - AllowInt16 = false; - Pref = []; - PrefHandles = []; - PrefHandlesAdvanced = []; - PrefHandlesPacs = []; - Synchonize = 0; - - Preview = []; - - %Video tools - StartTime = []; - Run = false; - Record = false; - LastPointer = 'arrow'; - LastPointerShapeCData = []; - VisibleThumbnails = []; - - Icons = []; - - ImageTypes = []; - ImageViewPlanes = []; - ImagingTechniques = []; - ImagingTechniquesFullNames = []; - - ThisFrameOnly = 1; - Synchronize=0; - StartFrame = 1; - - SegIntersection = []; - IntersectionIM = []; - ShowIntersectionMask = false; - - BalloonLevel = 0; - BALLOON = []; - EndoBalloonForce = []; - EpiBalloonForce = []; - LevelSet = []; - DATASETPREVIEW = []; - EndoEDGE0 = []; - EndoEDGE1 = []; - EndoEDGE2 = []; - EndoEDGE3 = []; - EpiEDGE0 = []; - EpiEDGE1 = []; - EpiEDGE2 = []; - EpiEDGE3 = []; - EndoEdgeDetected = 0; - EpiEdgeDetected = 0; - MovieFrame = []; - NumPoints = 80; - - Overlay = []; - - BpInt = 0; - MInt = [0,0]; - TInt = 0; - - Pin = []; - - MeasureX = []; - MeasureY = []; - MeasureT = []; - MeasureZ = []; - MeasureN = []; - MeasureName = []; - MeasureOffsetX = []; - MeasureOffsetY = []; - - CursorX = []; - CursorY = []; - CursorN = []; - CursorXOfs = []; - CursorYOfs = []; - imagecursor = []; - theta = linspace(0,2*pi,20); %this is used in timecritical cursor display therefore preallocated here. - - - NeedToSave = 0; - - Testing = false; %This property is used by maketest only. - RecordMacro = false; %Used by macro_helper; - Macro = []; %Used by macro_helper - MacroN = []; %Used by macro_helper - Buffer = []; %Used for macros and testing - - CineTimer = []; - SegmentServerMonitorTimer = []; - - contourp = []; - contourbimage = []; %used for dragging contours in lv.m - - MainMotionFcn = ''; - - DynamicPACS = []; - - LicenseNumber = ''; - PayPerCaseS = []; - - GPU = []; - - end - - methods - - %-------------------------------------- - function g = maingui(programversion) - %-------------------------------------- - %Constructor - %Initialization of Segment GUI - - %System settings - - %Removed this when we switched to R2014b since - %opengl software %This avoids the bullseye plot to get "partly upside down" on some computers. - - %Removed this when we switched to R2011a since this the bug with race - %condition in logical operands is elimenated since R2008b according to - %Mathworks. EH: - %maxNumCompThreads(1); %This (hopefully!) eliminates a loader bug problem, see ticket #598. - - pathname = getpreferencespath; - - g.ProgramVersion = programversion; - g.Buffer = clearbuffer; %Clear and initializes buffers used for macro purposes - - %Remove old logfiles - f = dir([pathname filesep '*.log']); - for loop=1:length(f) - if (now-f(loop).datenum)>7 - delete([pathname filesep f(loop).name]); - end; - end; - - %Remove old inbox files - f = dir([pathname filesep '*.inbox']); - for loop=1:length(f) - if (now-f(loop).datenum)>7 - delete([pathname filesep f(loop).name]); - end; - end; - - %Remove old outbox files - f = dir([pathname filesep '*.outbox']); - for loop=1:length(f) - if (now-f(loop).datenum)>7 - delete([pathname filesep f(loop).name]); - end; - end; - - g.initLogFile; - g.dispwelcometext; - - % Register where segment.m is located if we are running from source - % from another directory (JT 090402) - if isdeployed() - g.SegmentFolder = pwd; - else - [segmentfolder_, name_, ext_] = fileparts(which('segment')); %#ok - g.SegmentFolder = segmentfolder_; - clear segmentfolder_ name_ ext_ - end - - checkpath(g.SegmentFolder); %Ensure that segment directory is on the path - %This is important if the user switches directory, but even more important - %is that the package technology will not work. Matlab will crash badly when - %exiting on packaged functions when one change directory, and some other - %unknown places. - - %Here all that uses mygui should be added. - g.GUI.Segment = []; - g.GUI.AddComment = []; - g.GUI.AVPlane = []; - g.GUI.BrukerReader = []; - g.GUI.Bullseye = []; - g.GUI.CESSFPMaR = []; - g.GUI.Communicate = []; - g.GUI.CropLVStacks = []; - g.GUI.CTPerfusion = []; - g.GUI.DicomSorter = []; - g.GUI.ECVRegistration = []; - g.GUI.Flow = []; - g.GUI.FlowUnwrap = []; - g.GUI.Fusion = []; - g.GUI.GreyZoneHist = []; - g.GUI.GreyZoneHistAlt = []; - g.GUI.Hotkeys = []; - g.GUI.ImageStacksCT = []; - g.GUI.InterchangeDelineation =[]; - g.GUI.LCS2D = []; - g.GUI.LCS2DFlowCurves = []; - g.GUI.LevelSet = []; - g.GUI.LevelSetSpeedIM = []; - g.GUI.LongAxis = []; %GUI for longaxis plots - g.GUI.LVLongaxismotion = []; - g.GUI.LVSegmentation = []; - g.GUI.MOSlider = []; - g.GUI.OpenFile = []; - g.GUI.PacsCon = []; - g.GUI.PacsTransfer = []; - g.GUI.PapillarySlider = []; - g.GUI.PatientDataBase = []; - g.GUI.PatientDataBaseSelectStudies = []; - g.GUI.PatientDataBaseSendFiles = []; - g.GUI.PatientDataBaseSelectFiletype = []; - g.GUI.PatientInfo = []; - g.GUI.Perfusion = []; - g.GUI.PerfusionGraphs = []; - g.GUI.PerfusionMR = []; - g.GUI.PerfusionScoring = []; - g.GUI.Pressure = []; - g.GUI.PulseWaveVelocity = []; - g.GUI.Reformat = []; - g.GUI.ReportSheetGenerator = []; %GUI for generating reports - g.GUI.Report3DModel = []; - g.GUI.ROI = []; - g.GUI.RVSegmentation = []; - g.GUI.SegmentView = []; - g.GUI.SeriesSelector=[]; - g.GUI.SetImageDescription =[]; - g.GUI.SetImageInfo = []; - g.GUI.SliceReport = []; - g.GUI.SpectPlot3d = []; - g.GUI.SpectPlot2d = []; - g.GUI.SpectPerfusion = []; - g.GUI.SpectRegistration = []; - g.GUI.Spectconfirmcenter = []; - g.GUI.Spectdefectpreferences = []; - g.GUI.Strain = []; - g.GUI.StrainTagging = []; -% g.GUI.StrainShortAxis = []; -% g.GUI.StrainPolarPlot = []; - g.GUI.T2Star = []; - g.GUI.T2wMaR = []; - g.GUI.TransitTimeTool = []; - g.GUI.VolumePlot = []; - - g.GUISettings = []; - g.GUISettings.TopGapHeight=0.01; - g.GUISettings.BottomGapHeight = 0.013; - g.GUISettings.LeftGapWidth =0.12; - g.GUISettings.RightGapWidth=0.21; - g.GUISettings.ReportPanelPixelMax=220; - g.GUISettings.ThumbnailPanelWidth=100; - g.GUISettings.BackgroundColor=[0.94 0.94 0.94];%Will later be overwritten by preferences. -% g.GUISettings.ForegroundColor=[0 0 0]; %Will later be overwritten by preferences. - g.GUISettings.ButtonColor = [0.94 0.94 0.94];%[0.92 0.91 0.84]; - g.GUISettings.ButtonSelectedColor = [0.5 0.5 1]; %sometimes [0.6 0.6 0.6] - g.GUISettings.AxesColorDefault=[1 0.6 0.2]; - g.GUISettings.AxesColor = [1,1,1];%g.GUISettings.AxesColorDefault; - g.GUISettings.TimebarAxesColor = [0,0,0]; - g.GUISettings.BarColorDefault=[55 119 106]/256; - g.GUISettings.BarColor=[55 119 106]/256; - - g.GUISettings.ThumbLineColor = [1 0.6 0.2]; - g.GUISettings.ThumbFlowLineColor = [0.9 0.9 0.9]; - g.GUISettings.MontageBorder=true; - - g.GUISettings.IntersectColor=[1 0.4 0.2]; - g.GUISettings.BoxAxesLineSpec='-'; - g.GUISettings.SliceLineSpec='y-'; - g.GUISettings.SliceLineSpecMultiSlice='y-'; - g.GUISettings.SliceLineSpecOneSlice='y-'; - g.GUISettings.MeasureLineSpec={[1 1 0],'+', '-',2};%'w+-'; %Orange [0.91 0.41 0.17], pink [1 128/255 128/255], Ljus grå[.8 .8 .8], Orange [240/255 120/255 0] - g.GUISettings.MeasureLineMarkerSize=6;%6; % Lila [64/255 0 128/25 5], Brun [128/255 64/255 0], mörkt grön [0 64/255 0], grå [128/255 128/255 128/255] - g.GUISettings.BoxAxesColor=[0.1 0.1 0.1];%[0 0 0]; %[0.7 0.2 0.2]; %Blå [128/255 128/255 1], grön-blå [0 128/255 128/255], green-brown .5 .5 0] - g.GUISettings.VolumeAxesColor = [0 0 0]; - g.GUISettings.ViewPanelsTypeDefault='one'; - g.GUISettings.AskToExitProgram = true; - g.GUISettings.PointsEnabled = true; - g.GUISettings.ColorMapSize = 256; - g.GUISettings.ThumbnailSize = 256; - - %Added by eriks - g.AllowInt16=false; - g.GUISettings.DrawPointer='cross'; - g.GUISettings.MeasurePointer='cross'; - g.GUISettings.PapilarColor=0;%this is casted to uint8 and multiplied by 255 - g.GUISettings.VolumeColorGraph=[1 1 1]; - g.GUISettings.DefaultROISpec='b-'; - g.GUISettings.DefaultROIDrawColor='b'; - - %GUI positions default values - g.GUIPositions(1).FileName='monitor'; - g.GUIPositions(1).Position=get(0,'MonitorPosition');%normalized position - - g.GUIPositions(2).FileName='segment.fig'; - g.GUIPositions(2).Position=[0.05 0.05 0.9 0.85];%normalized position - - - - %load saved GUIpositions - try - g.loadguipositions; - catch - end - - end - - %-------------------------------------------------------------- - function inithideplaceholder(varargin) - %----------------------------------------------------------- - %Initiates the hideiconholder located to the top right of the gui. - g=varargin{1}; - - hideiconcell={}; - hideiconcell{1,end+1}=myicon('synchronize',g.Handles.hideiconholder,g.Icons.config.syncronize,'Synchronize all image stacks',@() segment('synchronize'),2); - hideiconcell{1,end+1}=myicon('singleframemode',g.Handles.hideiconholder,g.Icons.config.singleframemode,'Single frame mode',@() segment('thisframeonly_Callback',1,0) ,1,1); - hideiconcell{1,end+1}=myicon('allframesmode',g.Handles.hideiconholder,g.Icons.config.allframesmode,'All frames mode',@() segment('thisframeonly_Callback',0,0),1,1); - hideiconcell{1,end+1}=myicon('hideicons',g.Handles.hideiconholder,g.Icons.config.hideiconpanel,'Hide icons',@() segment('hidepanels'),2); - hideiconcell{1,end+1}=myicon('hideresult',g.Handles.hideiconholder,g.Icons.config.hideresultpanel,'Hide result panel',@() segment('hidepanels'),2); - g.Handles.hideiconholder.add(hideiconcell); - pos=plotboxpos(g.Handles.hideiconholder.axeshandle); - currentpos=get(g.Handles.hideiconholder.axeshandle,'position'); - currentpos(1)=currentpos(1)+1-(pos(1)+pos(3)); - set(g.Handles.hideiconholder.axeshandle,'position',currentpos);%-[pos(3),0,0,0]); - g.Icons.hidecell=hideiconcell; - end - - %-------------------------------------------- - function hidepanels(varargin) - %---------------------------------------------- - %The function hide all panels hides all panels and displays only image - %you can use the current tool - - g=varargin{1}; - %First check which state we want to toggle to - stateandicon = segment('iconson',{'hideresult','hideicons'}); - - if stateandicon{1,1} - %Start setting the visible command - set(g.Handles.barpanel,'Visible','off') - set(g.Handles.flowuipanel,'Visible','off') - set(g.Handles.lvuipanel,'Visible','off') - set(g.Handles.reportpanel,'Visible','off') - if any(strcmp(g.ProgramName,{'Segment 3DPrint'})) && strcmp(g.CurrentTheme,'3dp') - set(g.Handles.printuipanel,'Visible','off'); - end - g.GUISettings.BottomGapHeight = 0.02; - g.GUISettings.RightGapWidth = 0.02; - else - set(g.Handles.barpanel,'Visible','on') - set(g.Handles.flowuipanel,'Visible','on') - set(g.Handles.lvuipanel,'Visible','on') - set(g.Handles.reportpanel,'Visible','on') - if any(strcmp(g.ProgramName,{'Segment 3DPrint'})) && strcmp(g.CurrentTheme,'3dp') - set(g.Handles.printuipanel,'Visible','on'); - end - g.GUISettings.BottomGapHeight = 0.133; - g.GUISettings.RightGapWidth = 0.21; - end - - if stateandicon{2,1} - currentconfigpos = get(g.Handles.configaxes,'position'); - currenthidepos = get(g.Handles.hideaxes,'position'); - currentdatasetaxespos = get(g.Handles.datasetaxes,'position'); - currentreportpanelpos = get(g.Handles.reportpanel,'position'); - currentthumbnailsliderpos = get(g.Handles.thumbnailslider,'position'); - - - currentreportpanelpos(4)=1-currentconfigpos(4); - currentconfigpos(2)=1-currentconfigpos(4); - currenthidepos(2)=1-currentconfigpos(4); - currentdatasetaxespos(4)=1-currentconfigpos(4); - currentthumbnailsliderpos(4) = 1-currentconfigpos(4); - - set(g.Handles.configaxes,'position',currentconfigpos) - set(g.Handles.hideaxes,'position',currenthidepos) - set(g.Handles.datasetaxes,'position',currentdatasetaxespos) - set(g.Handles.reportpanel,'position',currentreportpanelpos); - - if any(strcmp(g.ProgramName,{'Segment 3DPrint'})) - currentprintpanelpos = get(g.Handles.printuipanel,'position'); - currentprintpanelpos(4)=1-currentconfigpos(4); - set(g.Handles.printuipanel,'position',currentprintpanelpos); - end - - set(g.Handles.thumbnailslider,'position',currentthumbnailsliderpos); - g.GUISettings.TopGapHeight = 0.06; - set(g.Handles.iconuipanel,'Visible','off') - - else - currentpanelpos = get(g.Handles.iconuipanel,'position'); - currentconfigpos = get(g.Handles.configaxes,'position'); - currenthidepos = get(g.Handles.hideaxes,'position'); - currentdatasetaxespos = get(g.Handles.datasetaxes,'position'); - currentreportpanelpos = get(g.Handles.reportpanel,'position'); - currentthumbnailsliderpos = get(g.Handles.thumbnailslider,'position'); - - currentdatasetaxespos(4)=currentpanelpos(2); - currentreportpanelpos(4)=currentpanelpos(2); - currentthumbnailsliderpos(4)=currentpanelpos(2); - currentconfigpos(2)=currentpanelpos(2); - currenthidepos(2)=currentpanelpos(2); - - if any(strcmp(g.ProgramName,{'Segment 3DPrint'})) - currentprintpanelpos = get(g.Handles.printuipanel,'position'); - currentprintpanelpos(4)=currentpanelpos(2); - set(g.Handles.printuipanel,'position',currentprintpanelpos); - end - - set(g.Handles.configaxes,'position',currentconfigpos) - set(g.Handles.hideaxes,'position',currenthidepos) - set(g.Handles.datasetaxes,'position',currentdatasetaxespos) - set(g.Handles.reportpanel,'position',currentreportpanelpos); - set(g.Handles.thumbnailslider,'position',currentthumbnailsliderpos); - g.GUISettings.TopGapHeight = 0.135; - set(g.Handles.iconuipanel,'Visible','on') - end - drawfunctions('drawall',g.ViewMatrix(1),g.ViewMatrix(2)) - %updatetool - - end - - %----------------------------------- - function togglebuttonLV_Callback(varargin) - %----------------------------------- - %Get clicked toggle button set and set configaxes - g=varargin{1}; - g.Handles.configiconholder.add(g.Icons.lviconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - g.CurrentTheme='lv'; - - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for LV this is the endo pen - iconcell=g.Icons.lviconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'endopen',1) - else - indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - - - %----------------------------------- - function togglebuttonRV_Callback(varargin) - %----------------------------------- - %Get clicked toggle button set and set configaxes - g=varargin{1}; - - g.Handles.configiconholder.add(g.Icons.rviconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - - g.CurrentTheme='rv'; - - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for RV this is the endo pen - iconcell=g.Icons.rviconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'rvendopen',1) - else - indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - - %----------------------------------- - function iconcell = togglebuttonAnalysis_Callback(varargin) - %----------------------------------- - %Get clicked toggle button set configuration - g=varargin{1}; - - g.Handles.configiconholder.add(g.Icons.analysisiconcell); - - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - - g.CurrentTheme='misc'; - - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for analysis this is the select tool - iconcell=g.Icons.analysisiconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'select',1) - else - indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - %----------------------------------- - function iconcell = togglebuttonROIFLOW_Callback(varargin) - %----------------------------------- - %Get clicked toggle button set configuration - g=varargin{1}; - g.Handles.configiconholder.add(g.Icons.roiflowiconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - g.CurrentTheme='roi'; - - - %If no button is indented in configplaceholder choose the initial - %buttons according to discussion with Helen - %for ROIFLOW this is the putroi tool - iconcell=g.Icons.roiflowiconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'putroi',1) - else - indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - - %----------------------------------- - function iconcell = togglebuttonImage_Callback(varargin) - %----------------------------------- - %Get clicked toggle button icon configuration - g=varargin{1}; - g.Handles.configiconholder.add(g.Icons.imageiconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - - g.CurrentTheme='misc'; - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for image this is the select tool - iconcell=g.Icons.imageiconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'select',1) - else - indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - - - %----------------------------------- - function iconcell = togglebuttontxmap_Callback(varargin) - %----------------------------------- - %Get clicked toggle button icon configuration - g=varargin{1}; - g.Handles.configiconholder.add(g.Icons.txmapiconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - - g.CurrentTheme='misc'; - - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for image this is the select tool - iconcell=g.Icons.txmapiconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'select',1) - else - indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - - %----------------------------------- - function iconcell = togglebutton3dp_Callback(varargin) - %----------------------------------- - %Get clicked toggle button icon configuration - g=varargin{1}; - g.Handles.configiconholder.add(g.Icons.printiconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - - g.CurrentTheme='3dp'; - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for image this is the select tool - iconcell=g.Icons.printiconcell; - clickedbutton=0; - - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - end - - if clickedbutton==0 - indent(g.Handles.configiconholder,'select',1) - %else - %indent(g.Handles.configiconholder,iconcell{clickedbutton}.name,1) - end - end - - %----------------------------------- - function iconcell = togglebuttonVia_Callback(varargin) - %----------------------------------- - %Get clicked toggle button icon configuration - g=varargin{1}; - g.Handles.configiconholder.add(g.Icons.viabilityiconcell); - pos=plotboxpos(g.Handles.configiconholder.axeshandle); - currentpos=get(g.Handles.configiconholder.axeshandle,'position'); - set(g.Handles.configiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - g.CurrentTheme='scar'; - - %If no button is indented in config place holder choose the initial - %buttons according to discussion with Helen - %for viability this is the select tool - iconcell=g.Icons.viabilityiconcell; - clickedbutton=0; - for i= 1:g.Handles.configiconholder.numberoficons - if iconcell{i}.isindented && iconcell{i}.type==1 - clickedbutton=i; - end - - if strcmp(iconcell{i}.name,'select') - ind=i; - end - end - - if clickedbutton==0 - iconcell{ind}.cdataDisplay=iconcell{ind}.cdataIndent; - iconcell{ind}.isindented=1; - feval(iconcell{ind}.execute); - else - iconcell{clickedbutton}.cdataDisplay=iconcell{clickedbutton}.cdataIndent; - iconcell{clickedbutton}.isindented=1; - feval(iconcell{clickedbutton}.execute); - end - g.Handles.configiconholder.render; - end - - %------------------------------------------------- - function toggleplaceholdermotion(varargin) - %------------------------------------------------- - %Handles the motion function so different functions can be triggered based on what object the cursor is over. - g=varargin{1}; - - handleAddress=hittest(g.fig); - - %get all iconholder in software check for dropdown iconholders - %aswell - iconholders = g.Handles.permanenticonholder; - iconholders = [iconholders,g.Handles.permanenticonholder.dropdowniconholders]; - - iconholders(end+1) = g.Handles.toggleiconholder; - iconholders = [iconholders,g.Handles.toggleiconholder.dropdowniconholders]; - - if ~isempty(get(g.Handles.configaxes,'Children')) - iconholders(end+1)=g.Handles.configiconholder; - iconholders = [iconholders,g.Handles.configiconholder.dropdowniconholders]; - end - - if ~isempty(get(g.Handles.hideaxes,'Children')) - iconholders(end+1)=g.Handles.hideiconholder; - iconholders = [iconholders,g.Handles.hideiconholder.dropdowniconholders]; - end - - for i = 1:length(iconholders) - if isequal(handleAddress,iconholders(i).imagehandle) - iconholders(i).motion; - else - iconholders(i).notover; - end - end - - -% -% -% if ~isempty(get(g.Handles.configaxes,'Children')) -% if isequal(handleAddress,g.Handles.configiconholder.imagehandle) -% g.Handles.configiconholder.motion -% else -% g.Handles.configiconholder.notover -% end -% end -% -% if isequal(handleAddress,g.Handles.permanenticonholder.imagehandle) -% g.Handles.permanenticonholder.motion -% else -% g.Handles.permanenticonholder.notover -% end -% -% if isequal(handleAddress,g.Handles.toggleiconholder.imagehandle) -% g.Handles.toggleiconholder.motion -% else -% g.Handles.toggleiconholder.notover -% end -% -% if ~isempty(get(g.Handles.hideaxes,'Children')) -% if isequal(handleAddress,g.Handles.hideiconholder.imagehandle) -% g.Handles.hideiconholder.motion -% else -% g.Handles.hideiconholder.notover -% end -% end -% -% if ~isempty(get(g.Handles.tempaxes,'Children')) -% if isequal(handleAddress,g.Handles.tempiconholder.imagehandle) -% g.Handles.tempiconholder.motion -% else -% g.Handles.tempiconholder.notover -% end -% end -% - end - - %------------------------------------ - function startmodeplaceholders(varargin) - %-------------------------------------- - % undents and disables all icons in toggleplaceholder. This is protocoll when no images - %are loaded - - g=varargin{1}; - - %empty config and permanent iconplaceholder - if isfield(g.Handles,'configiconholder') - for iconholder = g.Handles.configiconholder.dropdowniconholders - delete(iconholder.axeshandle) - iconholder.axeshandle = NaN; - delete(iconholder); - end - g.Handles.configiconholder.dropdowniconholders=[]; - delete(get(g.Handles.configaxes,'Children')) - g.Handles.configiconholder.cdata=[]; - end - - if isfield(g.Handles,'hideiconholder') - delete(get(g.Handles.hideaxes,'Children')) - g.Handles.hideiconholder.cdata=[]; - end - - g.initpermanentplaceholder; - iconcell=g.Handles.permanenticonholder.iconCell; - - icons2disable_ind=[2: numel(iconcell)-3]; - - for i = icons2disable_ind - iconcell{i}.disable; - end - - iconcell=g.Handles.toggleiconholder.iconCell; - - for i = 1:numel(iconcell) - iconcell{i}.disable; - end - g.Handles.toggleiconholder.disablepad=1; - g.Handles.toggleiconholder.render; - - iconcell=g.Handles.toggleiconholder.iconCell; - - for i = 1:numel(iconcell) - iconcell{i}.disable; - end - g.Handles.toggleiconholder.disablepad=1; - g.Handles.toggleiconholder.render; - % set(g.Handles.hideallpanelsradiobutton,'visible','off'); - - -% %Disable toggle buttons -% set([g.Handles.viabilitypushbutton,g.Handles.analysispushbutton,... -% g.Handles.leftventriclepushbutton,g.Handles.rightventriclepushbutton,g.Handles.roipushbutton,... -% g.Handles.imagepushbutton],'Enable','off') - - end - - %--------------------------------------------- - function setviewbuttons(varargin) - %--------------------------------------------- - %Assures that the correct view panel configuration and view panel mode - %buttons are indented. - g=varargin{1}; - - if nargin~=1 - runbuttons=varargin{2}; - else - runbuttons=1; - end - - %First the panel group is found - str=sprintf('%d%d',g.ViewMatrix(1),g.ViewMatrix(2)); - - namelist={'panel1','panel2','panel2x1','panel3','panel3x1','panel4','panel6','orthoview'}; - name=[]; - switch str - case '11' - name='panel1'; - case '12' - name='panel2'; - case '21' - name='panel2x1'; - case '13' - name='panel3'; - case '31' - name='panel3x1'; - case '22' - name='panel4'; - if strcmp(g.ViewPanelsType{1},'ortho') - name='orthoview'; - end - case '23' - name='panel6'; - %case '24' - %name='panel8'; - end - - %if~isempty(name) - ind=[]; - iconcell=g.Handles.permanenticonholder.iconCell; - for i= 1:g.Handles.permanenticonholder.numberoficons - if strcmp(iconcell{i}.name,name) - ind=i; - %shouldnt do anything if the icons are disabled i.e we are in start - %mode - if ~iconcell{i}.enabled - return; - end - end - if any(strcmp(iconcell{i}.name,namelist)) - iconcell{i}.undent - end - end - - if ~isempty(ind) - iconcell{ind}.cdataDisplay=iconcell{ind}.cdataIndent; - iconcell{ind}.isindented=1; - - if runbuttons - feval(iconcell{ind}.execute); - end - end - %end - %if viewpanels isempty assume viewone - % if isempty(g.ViewPanelsType) - % name='viewone'; - % else - ind=[]; - %Then view mode - switch g.ViewPanelsType{g.CurrentPanel} - case 'montage' - name='viewall'; - notortho = 1; - case 'one' - name='viewone'; - notortho = 1; - case 'montagerow' - name='viewrow'; - case {'ortho','gla','vla','hla'} - name = 'orthoview'; - end - - - % end - iconcell=g.Handles.permanenticonholder.iconCell; - for i= 1:g.Handles.permanenticonholder.numberoficons - if strcmp(iconcell{i}.name,name) - ind=i; - end - if any(strcmp(iconcell{i}.name,{'viewall','viewone','viewrow'})) - iconcell{i}.undent - end - end - - if ~isempty(ind) - iconcell{ind}.cdataDisplay=iconcell{ind}.cdataIndent; - iconcell{ind}.isindented=1; - - if runbuttons - feval(iconcell{ind}.execute); - end - end - g.Handles.permanenticonholder.render; - end - - - %------------------------------------ - function dataloadedplaceholders(varargin) - %-------------------------------------- - % When data is loaded the placeholders are all enabled - global SET - - g=varargin{1}; - - %updatetool('select'); - - g.initpermanentplaceholder; - g.inithideplaceholder; - - %g.setviewbuttons(1); - g.setviewbuttons(0); - -g.Handles.toggleiconholder.enable; -% for i = 1:numel(iconcell) -% iconcell{i}.enable; -% end -% - g.Handles.toggleiconholder.disablepad=0; - - switch g.CurrentTheme - case 'lv' - g.Handles.toggleiconholder.indent('ribbonlv',1); - case 'rv' - g.Handles.toggleiconholder.indent('ribbonrv',1); - case 'roi' - g.Handles.toggleiconholder.indent('ribbonflow',1); - case 'scar' - g.Handles.toggleiconholder.indent('ribbonviability',1); - case '3dp' - g.Handles.toggleiconholder.indent('ribbon3dp',1); - otherwise - g.Handles.toggleiconholder.indent('ribbonlv',1); - g.CurrentTheme='lv'; - end -% %asserts that first button is toggle button. -% iconcell{1}.cdataDisplay=iconcell{1}.cdataIndent; -% iconcell{1}.isindented=1; -% feval(iconcell{1}.execute); -% g.Handles.toggleiconholder.clickedicon=iconcell{1}; -% g.Handles.toggleiconholder.render; - - %Click the single frame mode button -% stateandicon = segment('iconson','singleframemode'); -% icon = stateandicon{1,2}; -% icon.cdataDisplay=icon.cdataIndent; -% icon.isindented=1; -% g.ThisFrameOnly = true; - - indent(g.Handles.hideiconholder,'singleframemode',1) - %synchronize click - indent(g.Handles.hideiconholder,'synchronize',1) - - %g.Handles.hideiconholder.render - %g.thisframeonly(1) - if ~isempty(SET(1).FileName) - str = sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),sprintf('Loaded file %s',SET(1).FileName),SET(1).PatientInfo.ID); - else - str = sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),sprintf('Loaded file %s',SET(1).PathName),SET(1).PatientInfo.ID); - end - g.adduserevent(str); - %g.adduserevent([' Loaded file: ', SET(1).FileName]) - %g.adduserevent(['Time:', datestr(now,'yyyymmddHHMMSS')]) - %g.adduserevent([' Patient name: ', SET(1).PatientInfo.Name]) - %g.adduserevent([' Patient ID: ', SET(1).PatientInfo.ID]) - - end - - - %--------------- - function init(g) - %--------------- - %Create GUI - g.initmaingui; - - loadpreferences; - - setuplicense; %This is done to set new license system in use - - if isequal(13,getmodule(12,'Ev',[],true)) - useragreement - if ~ishandle(g.fig) - %The software has been terminated - return - end - end - - if g.Pref.UserLogging - answer = yesno(sprintf('You are currently logged in as %s. Do you wish to proceed?',getenv('USERNAME'))); - - if answer == 0 - filemenu('quit_Callback','Aborting initialization.'); - return - else - - str = sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),'Software started.','-'); - fail = g.adduserevent(str); - if fail - - end - end - end - - setappdata(0,'UseNativeSystemDialogs',false); %this controls style of uigetdir - - % Generate a structure of handles and user data to pass to callbacks. - %handles = guihandles(g.fig); - - % Check for new versions of software - g.checkversion; - - %g.Handles=handles; - g.Handles.imageaxes = []; - g.Handles.boxaxes = []; - g.imagefig = g.fig; - - segment('resetpreview'); - g.Run = false; - g.Record = false; - g.LastPointer = 'arrow'; - g.LastPointerShapeCData = []; - g.VisibleThumbnails = []; - - %g.ExcludePapilars = g.Pref.ExcludePapilars; - %g.UseLight = g.Pref.UseLight; - - %Add some graphics - %Install icons - try - load('newicons.mat','newicons') - catch me - myfailed('Critical error: Could not read icons.',g); - mydispexception(me); - end; - - %not used but idea is to speed up searching for active icons - g.Icons.permanent = newicons; - g.Icons.config = newicons; - g.Icons.toggleicons = newicons; - - %added by eriks - set(g.fig,'WindowScrollWheelFcn',@(h,e) segment('changewheel_Callback',h,e)); - - %Create icon cell in which we place icons for desired appearance - g.Handles.toggleiconholder = myiconplaceholder(g.Handles.ribbonaxes,1); - g.Handles.permanenticonholder = myiconplaceholder(g.Handles.permanentaxes); - g.Handles.configiconholder = myiconplaceholder(g.Handles.configaxes); - g.Handles.hideiconholder = myiconplaceholder(g.Handles.hideaxes,0,2);%2 is that it drags to right - - %we must manage multiple axes so we need a hittest check for all - %available axeses - set(g.fig,'WindowButtonMotionFcn',@g.toggleplaceholdermotion); - - g.initribbonplaceholder; - g.initconfigplaceholder; - g.inithideplaceholder; - g.startmodeplaceholders - g.inittoolbar;%obsolete - - %--- Checks all parameterfiles, and fills listbox - if isdeployed - pathname = pwd; - else - temp = mfilename('fullpath'); - pathname = fileparts(temp); - end; - - f = dir([pathname filesep '*.par']); - names = cell(1,length(f)); - [names{:}] = deal(f(:).name); - - %Take away extension - for loop=1:length(names) - ind = find(names{loop}=='_'); - ind = ind(end); - names{loop} = names{loop}(1:(ind-1)); - end; - - %Remove duplicates - names = unique(names); - - %Load the files to check name - stri = cell(1,length(names)); - - for loop=1:length(names) - try - load([names{loop} '_endo.par'],'-mat'); - catch %#ok - load([names{loop} '_epi.par'],'-mat'); - end; - - %Remove 'endo' - tempstri = p.name; - ind = findstr(tempstri,' endo'); - if not(isempty(ind)) - tempstri = tempstri(1:(ind-1)); - end; - - %Remove 'epi' - ind = findstr(tempstri,' epi'); - if not(isempty(ind)) - tempstri = tempstri(1:(ind-1)); - end; - - %Store it - stri{loop} = tempstri; - end; - - g.ImagingTechniques = names; - g.ImagingTechniquesFullNames = stri; - - g.NeedToSave = false; - - %Close restores defaults. - g.filecloseall_Callback(true); %silent - - handles = [... - g.Handles.filemenu ... - g.Handles.utilitymenu ... - g.Handles.pluginmenu ... - g.Handles.helpmenu]; %... - %g.Handles.fileopenicon ... - %g.Handles.databaseicon ... - %g.Handles.importfromcdicon ... - %g.Handles.pacsicon]; - - set(handles,'enable','off'); - - g.versionhello; - - if ~g.Locked - try - set(handles,'enable','on'); - catch - end; - end; - - %This callback is set here to avoid error messages at startup - set(g.GUI.Segment.fig,'ResizeFcn','segment(''mainresize_Callback'')'); - - g.updatetitle; - - if ~g.Locked - - % Start sectramodule - sectra('initsectra'); - %Start externalpacsmodule - externalpacs('initexternalpacs'); - end; - - segpref('setbackgroundcolor',g.Pref.GUIBackgroundColor) - %g.init_userlogging - end - - %---------------------- - function initmaingui(g) - %---------------------- - %Initiates main GUI. Overloaded in most other GUI's - - g.GUI.Segment=mygui('segment.fig');%Load standard Segment GUI - g.fig = g.GUI.Segment.fig; - g.Handles = guihandles(g.fig); - g.Handles = killhandles(g.fig,{'segment.fig'}); - - colormap(gray(255)); %Moved this to here. - end - - %---------------------------- - function init_userlogging(g) - %---------------------------- - %Initiates user logging - val = mygetvalue(g.PrefHandlesAdvanced.userloggingcheckbox); - - if val == 1 - %Initiate log file. - pathname = g.Pref.UserLogPath; - %g.UserFile = [pathname filesep sprintf('segmentuserlog.log')]; - fid = fopen(pathname,'a'); - if isequal(fid,-1) - myfailed(dprintf('Could not write to user log path %s \n User logging is turned off.',pathname)); - g.Pref.UserLogPath=[]; - g.Pref.UserLogging = 0; - %if isopen('segpref.fig') - set(g.PrefHandlesAdvanced.userloggingcheckbox,'Value',0); - set(g.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); - %end - return; - end; - fclose(fid); - adduserevent(g,sprintf('%s\t%s\t%s\t%s','DATE','USER','EVENT','PATIENT ID')); - adduserevent(g,sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),'Started user log','-')); - end - end - - %--------------------------------- - function fail = adduserevent(g,str) - %--------------------------------- - %Adds event to user log - fail = 0; - if g.Pref.UserLogging - fid = fopen(g.Pref.UserLogPath,'a'); - if fid == -1 - fail=1; - myfailed(dprintf('User logging turned off.\n Since unable to write to .txt file: \n %s.',g.Pref.UserLogPath)); - g.Pref.UserLogPath=[]; - g.Pref.UserLogging = 0; - return - end - %mydisp(str) - fprintf(fid,'%s\r\n',str); - fclose(fid); - end - end - - %---------------------- - function initLogFile(g) - %---------------------- - %Initiate log file. Overloaded in most other GUI's - pathname = getpreferencespath; - g.LogFile = [pathname filesep sprintf('segmentlog_%s.log',datestr(now,'yyyymmddHHMMSS'))]; - fid = fopen(g.LogFile,'w'); - if isequal(fid,-1) - myfailed(dprintf('Could not create .log file %s.',g.LogFile)); - else - fclose(fid); %Close the file, to make it empty - g.startlog(g.LogFile); %Start diary. - end; - end - - %-------------------------- - function inittoolbar(g) - %-------------------------- - %Initiates toolbars. Overloaded in CVQgui, Segment CMR gui and RVQgui - %g.initmaintoolbar; - %segment('initviewtoolbar'); - segment('initmenu'); - end - - %-------------------------- - function initmaintoolbar(g) - %-------------------------- - %Initiate main toolbar. Overloaded in any GUI with a toolbar - end - - %---------------------- - function updatetitle(g) - %---------------------- - %Updates titleline of main GUI. Overloaded in CVQgui and RVQgui - global SET NO - - if g.Silent - return; - end; - - if (NO<1)||(NO>length(SET)) - no = 1; - else - no = NO; - end; - - licensename = getmodule('getlicensename'); - if (isempty(licensename)|isnan(licensename)) %#ok - name = '(Academic Research only version)'; - else - name = ['(' deblank(licensename') ')']; - end; - titlestring = strcat([g.ProgramName ... - ' v' g.ProgramVersion ... - ' ' name]); - - if g.Pref.AnonymMode - set(g.imagefig,'name',... - sprintf('%s',titlestring)); - else - if isempty(SET) - location= ''; - else - location = sprintf('/ %s %s',SET(no).PatientInfo.Name,SET(no).PatientInfo.ID); - end - set(g.imagefig,'name',... - sprintf('%s %s',titlestring,location)); - end; - - end - - - %------------------------------------- - function orthoview_Buttondown(g,panel) - %------------------------------------- - %Switch to slices corresponding to location of user click - global NO - - - - segment('switchtopanel',panel);%segment_main('normal_Buttondown',panel); - set(g.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - [y,x] = mygetcurrentpoint(g.Handles.imageaxes(panel)); - silent = true; - switch g.ViewPanelsType{panel} - case 'ortho' - segment('switchtolongaxisslice',round(x),'HLA',silent); - segment('switchtolongaxisslice',round(y),'VLA'); - case 'hla' - segment('switchtolongaxisslice',round(y),'VLA',silent); - segment('switchtoslice',round(x)); - case 'vla' - segment('switchtolongaxisslice',round(y),'HLA',silent); - segment('switchtoslice',round(x)); - case 'gla' - [vslice,hslice] = calcfunctions('gla2sax',x,y,NO); - segment('switchtolongaxisslice',round(vslice),'HLA',silent); - segment('switchtolongaxisslice',round(hslice),'VLA',silent); - segment('switchtoslice',round(x)); - end - end - - %------------------------------------- - function glarotatehandle_Buttondown(g) - %------------------------------------- - %Rotate GLA view using handle on intersection line - global SET NO - - segment_main('normal_Buttondown',1); - glaangle = SET(NO).GLA.angle; - panel = g.CurrentPanel; - - xhan = get(g.Handles.glarotatehandle(panel),'XData'); - yhan = get(g.Handles.glarotatehandle(panel),'YData'); - xhan = xhan(2); - yhan = yhan(2); - set(g.Handles.glarotatehandle(panel), ... - 'XData',xhan+1000*cos(glaangle)*[-1 0 1], ... - 'YData',yhan+1000*sin(glaangle)*[-1 0 1], ... - 'LineStyle','-'); - set(g.fig,'WindowButtonMotionFcn','segment(''glarotatehandle_Motion'')'); - set(g.fig,'WindowButtonUpFcn','segment(''glarotatehandle_Buttonup'')'); - end - - %--------------------------------- - function glarotatehandle_Motion(g) - %--------------------------------- - %Motion fcn for using GLA view rotation handle - global SET NO - panel = g.CurrentPanel; - [x,y] = mygetcurrentpoint(g.Handles.imageaxes(panel)); - glaangle = mod(atan2(SET(NO).ResolutionX*(y-SET(NO).HLA.slice), ... - SET(NO).ResolutionY*(x-SET(NO).VLA.slice))+pi/2,pi)-pi/2; - set(g.Handles.glarotatehandle(panel), ... - 'XData',x+1000/SET(NO).ResolutionY*cos(glaangle)*[1 0 -1], ... - 'YData',y+1000/SET(NO).ResolutionX*sin(glaangle)*[1 0 -1]); - SET(NO).GLA.angle = glaangle; - end - - %----------------------------------- - function glarotatehandle_Buttonup(g) - %----------------------------------- - %Update view according to new rotation - global NO - set(g.fig,'WindowButtonMotionFcn',[], ... - 'WindowButtonUpFcn',[]); - set(g.Handles.glarotatehandle(g.CurrentPanel),'LineStyle','none'); - segment_main('updateoneim',NO); - drawfunctions('updatenopanels',NO); - drawfunctions('drawintersections'); - end - - %-------------------------- - function dispwelcometext(g) - %-------------------------- - %Displays welcome text. Overloaded in CVQgui, SegmentCMR GUI - mydisp('Welcome to Segment, Software for Cardiac Image Analysis'); - mydisp(' '); - mydisp(['Software version ' g.ProgramVersion ' Copyright Einar Heiberg, Medviso AB (http://www.medviso.com)']); - mydisp(' '); - mydisp('In this window system and error messages will appear.'); - mydisp('Do not close this window.'); - mydisp(' '); - end - - %--------------------------- - function loadguipositions(g) - %--------------------------- - %Load prestored positions of GUI's. - - pathname = getpreferencespath; - - if ispc - if not(exist([pathname filesep '.segment_guipositions.mat'],'file')) - %mywarning('Moving system preferences file to new user location.'); - mydisp('Moving system preferences file to new user location.'); - end; - end; - - %Try to find a more suitable place for the file - %try - load([pathname filesep '.segment_guipositions.mat'],'GUIPositions'); - %names={GUIPositions.FileName}; - %ind=find(strcmp(names,'monitor')); - - mp = get(0,'MonitorPositions'); -% ss = get(0,'ScreenSize'); -% for mploop = 1:4, sameposition(mploop) = mp(1,mploop) == ss(1,mploop); end -% if sum(sameposition) < 4 -% mp = ss; -% end - %return to default and introduce new guipositions field monitor - if ~strcmp(GUIPositions(1).FileName,'monitor') - DATA.GUIPositions=[]; - DATA.GUIPositions(1).FileName=monitor; - DATA.GUIPositions(1).Position=mp; - return; - end - - prevmp=GUIPositions(1).Position; - - if all(size(mp)==size(prevmp)) && all(mp==prevmp) - g.GUIPositions = GUIPositions; %#ok - else - DATA.GUIPositions=[]; - return - end -% -% if monitor -% %check if only one monitor and positions outside this monitor -% %then change guipositions to be inside the monitor -% monitorpositions = get(0,'MonitorPositions'); -% numbermonitors = size(monitorpositions,1); -% if numbermonitors == 1 -% for loop=1:length(g.GUIPositions) -% pos = g.GUIPositions(loop).Position; -% if pos(1)>=1 || pos(1)<0 || pos(2)>=1 || pos(2)<0 -% pos(1)=pos(1)-floor(pos(1)); -% pos(2)=pos(2)-floor(pos(2)); -% if pos(3)>1 -% pos(3)=1; -% end -% if pos(4)>1 -% pos(4)=1; -% end -% g.GUIPositions(loop).Position=pos; -% end -% end -% end -% catch me -% mydispexception(me); -% mydisp('Could not read guipositions. Probably a new installation.'); -% end; -% end - end - - %------------------------------------ - function enableplaceholders(varargin) - %-------------------------------------- - % Enables all icons in toggleplaceholder. This is protocoll when images - %are loaded - - g=varargin{1}; - - iconcell=g.Handles.toggleiconplaceholder.iconcell; - - for i = 1: numel(iconcell) - iconcell{i}.enable; - end - end - - %------------------------------------ - function filecloseall_Callback(g,silent) %#ok - %------------------------------------ - %Deletes all image stacks and resets Segment to original state. - %Overloaded in CVQgui and RVQgui - global SET NO - - if (g.NeedToSave)&&(nargin==1) - if ~yesno('Unsaved changes: are you sure you want to close all image stacks?',[],g.GUI.Segment); - return; - end; - end; - - %Undent and disable all the toggle buttons - - g.startmodeplaceholders - if any(strcmp(g.ProgramName,{'Segment CT'})) - g.CurrentTool = 'select'; - g.CurrentTheme = 'lv'; - set([... - g.Handles.pointsmenu ... - ],'enable','off'); - end - if any(strcmp(g.ProgramName,{'Segment 3DPrint'})) - set(g.Handles.printuipanel,'Visible','off') - g.CurrentTool = 'select'; - g.CurrentTheme = 'lv'; - set([... - g.Handles.threedpmenu ... - g.Handles.pointsmenu ... - ],'enable','off'); - end - flushlog; - - g.Silent = false; - g.LastSaved = now; - g.ViewPanels = []; - g.ViewPanelsType = {}; - g.ViewPanelsMatrix = {}; - g.ViewIM = {}; - g.Overlay = []; - g.ViewMatrix = []; - g.CurrentPanel = 1; - g.Undo = []; - g.UndoN = []; - g.VisibleThumbnails = []; - g.DATASETPREVIEW = []; - - %Close all associated GUIs - g.closeallnoguis(1:numel(SET)); - - %clear functions; %EH: Removed 2010-08-22 - - %Delete window - try - delete(g.Handles.imageaxes); - g.Handles.imageaxes = []; - delete(g.Handles.boxaxes); - g.Handles.boxaxes = []; - catch %#ok - end; - - %Disable non-valid options. - %g.Handles.pointsmenu ... - %g.Handles.threedpmenu ... - set([... - g.Handles.measuremenu ... - g.Handles.toolsmenu ... - g.Handles.roimenu ... - g.Handles.editmenu ... - g.Handles.exportmenu ... - g.Handles.viewmenu .... - g.Handles.segmentmenu ... - g.Handles.mrmenu ... - g.Handles.viabilitymenu ... - g.Handles.flowmenu ... - g.Handles.ctmenu ... - g.Handles.spectmenu ... - g.Handles.lvmenu ... - g.Handles.rvmenu ... - g.Handles.analysismenu ... - g.Handles.fileloadsegmentationmenu ... - g.Handles.fileloadnextmenu ... - g.Handles.filesavesegmentationmenu ... - g.Handles.filesavecurrentmenu ... - g.Handles.filesaveallmenu ... - g.Handles.filesaveallasmenu ... - g.Handles.filesavetodatabasemenu ... - g.Handles.filesavetopacsmenu ... - g.Handles.filesavesegdicom ... - g.Handles.fileclosecurrentimagestack ... - g.Handles.filecloseallmenu ... - g.Handles.fileclosemultiplemenu ... - g.Handles.filesavesubmenu ... - g.Handles.thumbnailslider... - ],'enable','off'); - - set(g.imagefig,'keypressfcn','','name',... - sprintf(strcat([g.ProgramName ' v' g.ProgramVersion]))); - - %clear the measurementresultaxes before closing - g.measurementreportclear; - - set([... - g.Handles.datasetaxes ... - g.Handles.reportpanel ... - g.Handles.barpanel ... - g.Handles.flowaxes ... - g.Handles.timebaraxes ... %g.Handles.excludepapilarscheckbox ... %g.Handles.uselightcheckbox ...g.Handles.thistimeframeonlycheckbox ... - ],... - 'visible','off'); - - set([... - g.Handles.thumbnailslider... - ],'visible','off'); - - %kill of children in timebar and volumeaxes. - cla(g.Handles.timebaraxes); - g.Handles.timebar = []; - g.Handles.timebaraxeshelpers=[]; - g.Handles.edtimebartext=[]; - g.Handles.estimebartext=[]; - g.Handles.edtimebarline=[]; - g.Handles.estimebarline=[]; - - cla(g.Handles.volumeaxes); - g.Handles.timebarlv = []; - g.Handles.volumecurve = []; - g.Handles.masscurve = []; - g.Handles.rvvcurve = []; - g.Handles.volumeaxeshelpers = []; - g.Handles.estext=[]; - g.Handles.edtext=[]; - g.Handles.esline=[]; - g.Handles.edline=[]; - g.Handles.lvmtext=[]; - - if g.DataLoaded - set(get(g.Handles.volumeaxes,'Children'),'visible','off'); - set(get(g.Handles.datasetaxes,'Children'),'visible','off'); - set(get(g.Handles.flowaxes,'Children'),'visible','off'); - set(get(g.Handles.timebaraxes,'Children'),'visible','off'); - end; - - g.ThisFrameOnly = true; - g.Synchronize=0; - g.GUISettings.AxesColor=[1,1,1];%g.GUISettings.AxesColorDefault; - - %Close potentially open figs. More might be added to this list - if isa(g.GUI.GreyZoneHistAlt,'mygui') - greyzonehist_alt('close_Callback'); - end - - %Setup preferences - g.DataLoaded = 0; - g.Run = 0; - - %Current view and slice - g.StartFrame = 1; - - %Make sure data is removed, store memory - g.BalloonLevel = 0; - g.BALLOON = []; - g.EndoBalloonForce=[]; - g.EpiBalloonForce=[]; - g.cleardatalevelset; - g.DATASETPREVIEW = []; - g.EndoEDGE0 = []; - g.EndoEDGE1 = []; - g.EndoEDGE2 = []; - g.EndoEDGE3 = []; - g.EpiEDGE0 = []; - g.EpiEDGE1 = []; - g.EpiEDGE2 = []; - g.EpiEDGE3 = []; - g.EndoEdgeDetected = false; - g.EpiEdgeDetected = false; - g.MovieFrame = []; - g.NumPoints = g.Pref.NumPoints; %Constant... - NO = 1; - SET = []; - g.NeedToSave = false; - - set(g.fig,'pointer','arrow'); - - drawnow; - - g.startmodeplaceholders - % JU: Set mode back to select (from SpecialGUI) - % this only matters if not opening a .mat file - if ~isempty(g) - if g.DataLoaded - updatetool('select'); - end - end - flushlog; - end - - %----------------------------- - function closeallnoguis(g,nos) - %----------------------------- - %Close all GUIs associated with one of image stacks nos - allguis = fieldnames(g.GUI); - for i = 1:numel(allguis) - gui = g.GUI.(allguis{i}); - if isa(gui,'mygui') - for no = nos - try - didclose = closeifhasno(gui,no); - catch %#ok - %If failed assume it is already closed. - g.GUI.(allguis{i}) = []; - end; - if didclose - g.GUI.(allguis{i}) = []; - break - end - end - end - end - end - - %--------------------------------- - function setthisframeonly(g,value) - %--------------------------------- - %Callback to set this frame only mode. - - if nargin<2 - value=g.ThisFrameOnly; - end - - g.ThisFrameOnly=value; - -% if ~strcmp(DATA.ProgramName,'Segment CMR') -% set(g.Handles.thistimeframeonlycheckbox,'value',value); -% end - - end - -% ----------------------------- -% function framemode_Callback(varargin) -% ----------------------------- -% global DATA -% g=varargin{1}; -% singlebutton=g.handles.singleframemodepushbutton; -% multibutton=g.handles.multiframemodepushbutton; -% if g.ThisFrameOnly -% thisframeonly_Callback(g,~val,silent) -% else -% -% end -% end - - %----------------------------------------------- - function thisframeonly_Callback(g,thisframeonly,silent) - %----------------------------------------------- - %Sets segment in 'this frame only' mode. Changes made to segmentation, - %copying etc are performed only for the current timeframe. - - if nargin<3 - silent=false; - end - - %We should change setting - if not(isequal(thisframeonly,g.ThisFrameOnly)) - g.ThisFrameOnly=thisframeonly; - - if g.ThisFrameOnly - g.GUISettings.AxesColor=[1 1 1]; - g.GUISettings.SliceLineSpec=g.GUISettings.SliceLineSpecOneSlice; - else - g.GUISettings.AxesColor=g.GUISettings.AxesColorDefault; - g.GUISettings.SliceLineSpec=g.GUISettings.SliceLineSpecMultiSlice; - end - - g.setthisframeonly(g.ThisFrameOnly); - - %Call to update drawimage to get frame around panel with correct - %color. - if not(silent) - set(g.Handles.imageaxes(g.CurrentPanel), 'xcolor',g.GUISettings.AxesColor,... - 'ycolor',g.GUISettings.AxesColor, 'linewidth',2.5, 'visible','on'); - end - end - - end - - %---------------------------- - function cleardatalevelset(g) - %---------------------------- - %Clear the struct g.LevelSet properly called when switching image - %stacks. - g.LevelSet.SpeedIM = []; - g.LevelSet.EDGE0 = []; - g.LevelSet.EDGE1 = []; - g.LevelSet.GradientPart = []; - end - - %--------------------- - function togglescar(g) - %--------------------- - %Called by segment('updateviewicons'). Overloaded in CVQgui. - global SET NO - if (SET(NO).TSize >1) - set(g.Handles.scarpushbutton,'enable','off'); - newscar = 'off'; - viability('viabilitymenu'); - elseif (SET(NO).TSize == 1) - set(g.Handles.scarpushbutton,'enable','on'); - newscar = 'on'; - viability('viabilitymenu'); - end - if strcmp(g.CurrentTheme,'scar') && strcmp(newscar,'off') -% g.updateicons('lv'); - end - end - - %---------------------------- - function fileopen_Callback(g) - %---------------------------- - %Loads a set of files as a 4D volume, and also updates preferences. - %Calls the fcn openfile which displays the fileloader GUI. - %Overloaded in CVQgui, Segment CMR gui, Segment SPECT gui. - global SET - - segment('stopmovie_Callback'); - %set(g.Handles.fileopenicon,'state','off'); - - - if ~isempty(SET) - m = mymenu('Image stacks already exist',... - {'Replace existing image stacks',... - 'Add image stacks to existing'},g.GUI.Segment); - - switch m - case 0 - return; - case 1 - %close existing image stacks before loading - silent = true; - g.filecloseall_Callback(); %not silent - case 2 - % do nothing, image stacks should be added to the existing image - % stacks - end; - end - %Call loading helper program. - oldpointer=get(g.imagefig,'pointer'); - set(g.imagefig,'pointer','arrow'); - openfile; - set(g.imagefig,'pointer',oldpointer); - - end - - %------------------------------------------------- - function fail = filesaveallas_Callback(g,varargin) - %------------------------------------------------- - %'Save as' callback. Overloaded in GUI's that save to database as - %default - fail = filemenu('saveallas_helper',varargin{:});%save image stacks and segmentations - end - - %------------------------ - function really = quit(g) - %------------------------ - %Quit segment, also ask user if he/she is sure. - %Overloaded in CVQgui - - really = true; - if (g.DataLoaded && g.GUISettings.AskToExitProgram) - if g.NeedToSave && ... - ~yesno('Unsaved changes: are you sure you want to quit the program?') - really = false; - return - end - if ~yesno('Are you sure that you want to close all image stacks?',[],g.GUI.Segment); - really = false; - return; - end - end; - - sectra('stopsectra'); - externalpacs('stopexternalpacs'); - - flushlog; - end - - %------------------------------ - function renderstacksfrommat(g) - %------------------------------ - %This function displays stacks from a mat files in main gui. - %Typically called upon loading; - global SET NO - - %Do not mess with .Silent here since it will be taken care of by lower - %routine images. - - if ~strcmp(g.ProgramName,'Segment 3DPrint') && isempty(g.ViewPanels) && ~isempty(SET(1).View) && strcmp(SET(1).View.CurrentTheme,'3dp') %fixes backwards compatibility with trying to load files from CT 3dp edition into CT. - SET(1).View = []; - end - - %Check if viewing preferences are stored in file. - if ~isempty(g.ViewPanels) - % addtopanels(no); % this is messy when mat files are loaded into mat - % files, etc. Just do thing. - % NO=g.ViewPanels(g.CurrentPanel); - % no=NO; - drawfunctions('drawall'); - segment('switchtopanel',g.CurrentPanel); - elseif isempty(SET(1).View) - g.ViewPanels = []; - g.ViewPanelsType = {}; - g.ViewPanelsMatrix = {}; - g.ViewIM = {}; - g.Overlay = []; - g.ViewMatrix = [1 1]; - g.CurrentPanel = 1; - g.CurrentTool = 'select'; - g.CurrentTheme = 'lv'; - segment('addtopanels',1); - drawfunctions('drawall'); - segment('switchtopanel',g.CurrentPanel); - else - g.ViewPanels = SET(1).View.ViewPanels; - g.ViewPanelsType = SET(1).View.ViewPanelsType; - g.ViewPanelsMatrix = SET(1).View.ViewPanelsMatrix; - if ~isfield(SET(1).View,'CurrentTheme') - g.CurrentTheme = 'lv'; - SET(1).View.CurrentTheme='lv'; - else - g.CurrentTheme = SET(1).View.CurrentTheme; - end - g.ViewIM = cell(1,length(g.ViewPanels)); - g.Overlay = struct('alphadata',[],'cdata',[]); - g.Overlay(length(g.ViewPanels)) = struct('alphadata',[],'cdata',[]); - if isfield(SET(1).View,'ViewMatrix') - g.ViewMatrix = SET(1).View.ViewMatrix; - else - g.ViewMatrix = []; - end; - if isfield(SET(1).View,'CurrentPanel') - g.CurrentPanel = SET(1).View.CurrentPanel; - else - g.CurrentPanel = 1; - end; - - NO = g.ViewPanels(g.CurrentPanel); - - if isfield(SET(1).View,'ThisFrameOnly') - %Now default is always on. - SET(1).View.ThisFrameOnly=1; - g.ThisFrameOnly = SET(1).View.ThisFrameOnly; - g.GUISettings.AxesColor=[1 1 1]; - g.setthisframeonly(g.ThisFrameOnly); - end; - if isfield(SET(1).View,'CurrentTheme') - if strcmp(g.CurrentTheme,'3dp') - segment3dp.tools('init3DP',1,1) - end - end; - end; - drawfunctions('drawthumbnails',isempty(g.DATASETPREVIEW)); %False means no calcpreview - mydisp('Image stacks loaded.'); - - %Enable all icons - drawfunctions('drawall',g.ViewMatrix); - g.dataloadedplaceholders - flushlog; - end - - %------------------------- - function updateicons(g,mode) - %------------------------- - %Updates icons when new mode is selected. - %Overloaded in Segment GUI, CVQgui, RVQgui and Segment CMR GUI - % If making major changes, make sure to - % update csegment('updateicons')!!! /JU - - global SET NO - - if nargin<2 - mode = g.CurrentTheme; - end; - - % if ismember(mode,{'scar'}) && (SET(NO).TSize>1) - % if ~g.Silent - % myfailed('Scar tools not enabled for time-resolved data. Perhaps delete time frames?',g.GUI.Segment) - % end - % return; - % end - - %Reset Tool structure - g.Tools = []; - - %Always - g.Tools.selectslices = g.Handles.selectslicespushbutton; - g.Tools.contrastbrightness = g.Handles.contrastbrightnesspushbutton; - g.Tools.move = g.Handles.movepushbutton; - g.Tools.scale = g.Handles.scalepushbutton; - g.Tools.undo = g.Handles.undopushbutton; - g.Tools.click3d = []; - - - %LV - g.Tools.endopen = []; - g.Tools.epipen = []; - g.Tools.autolv = []; - g.Tools.autoendo = []; - g.Tools.autoepi = []; - g.Tools.refineendo = []; - g.Tools.refineepi = []; - g.Tools.removepapilar = []; - g.Tools.putendopin = []; - g.Tools.putepipin = []; - g.Tools.clearlv = []; - g.Tools.interpendo = []; - g.Tools.interpepi = []; - g.Tools.expandendo = []; - g.Tools.contractendo = []; - g.Tools.expandepi = []; - g.Tools.contractepi = []; - - %RV - g.Tools.rvendopen = []; - g.Tools.rvepipen = []; - g.Tools.autorvendo = []; - g.Tools.autorvepi = []; - g.Tools.refinervendo = []; - g.Tools.putrvendopin = []; - g.Tools.clearrv = []; - g.Tools.interprvendo = []; - g.Tools.interprvepi = []; - - %ROI - g.Tools.roipen = []; - g.Tools.putroi = []; - g.Tools.refineroi = []; - g.Tools.refineroinext = []; - g.Tools.trackroi = []; - g.Tools.roicolor = []; - g.Tools.roitext = []; - g.Tools.roiclear = []; - - %Scar - g.Tools.scarpen = []; - g.Tools.mopen = []; - g.Tools.autoscar = []; - g.Tools.rubberpen = []; - g.Tools.rubber = []; - g.Tools.scarundo = []; - g.Tools.hideoverlay = []; - - %Misc - g.Tools.point = []; - g.Tools.measure = []; - g.Tools.crop = []; - g.Tools.flipx = []; - g.Tools.flipy = []; - g.Tools.rotate90 = []; - - %View - g.Tools.viewcinescar = []; - g.Tools.viewcinescarperf = []; - g.Tools.viewstress = []; - g.Tools.viewflow = []; - - %MaR - g.Tools.marauto = []; - g.Tools.marhide = []; - g.Tools.marpen = []; - g.Tools.marrubberpen = []; - g.Tools.marrubber = []; - - %Reset all - if ~strcmp(mode,g.CurrentTheme) - set([... - g.Handles.icon01 ... - g.Handles.icon02 ... - g.Handles.icon03 ... - g.Handles.icon04 ... - g.Handles.icon05 ... - g.Handles.icon06 ... - g.Handles.icon07 ... - g.Handles.icon08 ... - g.Handles.icon09... - g.Handles.icon10 ... - g.Handles.icon11 ... - g.Handles.icon12 ... - g.Handles.icon13 ... - g.Handles.icon14... - g.Handles.icon15],... - 'cdata',[],'Callback','','Tooltipstring','', ... - 'Interruptible','on','backgroundcolor',g.GUISettings.ButtonColor); - end - - set([... - g.Handles.leftventriclepushbutton ... - g.Handles.rightventriclepushbutton ... - g.Handles.t2starpushbutton ... - g.Handles.perfusionpushbutton ... - g.Handles.roipushbutton ... - g.Handles.scarpushbutton ... - g.Handles.marpushbutton ... - g.Handles.reservedpushbutton ... - g.Handles.annotationspushbutton ... - g.Handles.tipushbutton ... - g.Handles.viewpushbutton ... - ],... - 'backgroundcolor',g.GUISettings.ButtonColor); - - oldtheme = g.CurrentTheme; - switch mode - case 'lv' - g.CurrentTheme = 'lv'; - set(g.Handles.leftventriclepushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - - g.Tools.autolv = g.iconcdatahelper(g.Handles.icon01,g.Icons.autolv,'Automatic segmentation of left ventricle (Ctrl-L)'); - g.Tools.refineendo = g.iconcdatahelper(g.Handles.icon02,g.Icons.refineendo,'Refine endocardium (Ctrl-R)'); - g.Tools.refineepi = g.iconcdatahelper(g.Handles.icon03,g.Icons.refineepi,'Refine epicardium (Ctrl-Shift-R)'); - g.Tools.putendopin = g.iconcdatahelper(g.Handles.icon04,g.Icons.putendopin,'Put endocardial pins that attract the contour'); - g.Tools.putepipin = g.iconcdatahelper(g.Handles.icon05,g.Icons.putepipin,'Put epicardial pins that attract the contour'); - %g.Tools.clearlv = g.iconcdatahelper(g.Handles.icon05,g.Icons.trash,'Clear LV segmentation in selected slices'); - - g.Tools.interpendo = g.iconcdatahelper(g.Handles.icon06,g.Icons.interpendo,'Draw endocardium by point interpolation (Shift-B)'); - g.Tools.endopen = g.iconcdatahelper(g.Handles.icon07,g.Icons.endopen,'Manually draw left ventricle endocardium (Shift-N)'); - g.Tools.expandendo = g.iconcdatahelper(g.Handles.icon08,g.Icons.expandendo,'Expand endocardium (Ctrl-E)'); - g.Tools.contractendo=g.iconcdatahelper(g.Handles.icon09,g.Icons.contractendo,'Contract endocardium (Ctrl-K)'); - g.Tools.propagateendo = g.iconcdatahelper(g.Handles.icon10,g.Icons.propagateendo,'Propagate endocardium forward and refine (Ctrl-F)'); - - g.Tools.interpepi = g.iconcdatahelper(g.Handles.icon11,g.Icons.interpepi,'Draw epicardium by point interpolation (Shift-H)'); - g.Tools.epipen = g.iconcdatahelper(g.Handles.icon12,g.Icons.epipen,'Manually draw left ventricle epicardium (Shift-G)'); - g.Tools.expandepi = g.iconcdatahelper(g.Handles.icon13,g.Icons.expandepi,'Expand epicardium (Ctrl-Alt-E)'); - g.Tools.contractepi= g.iconcdatahelper(g.Handles.icon14,g.Icons.contractepi,'Contract epicardium (Ctrl-Alt-K)'); - g.Tools.propagateepi = g.iconcdatahelper(g.Handles.icon15,g.Icons.propagateepi,'Propagate epicardium forward and refine (Ctrl-Shift-F)'); - - %callbacks - g.iconcallbackhelper(g.Tools.endopen,'drawendo'); - g.iconcallbackhelper(g.Tools.epipen,'drawepi'); - g.iconcallbackhelper(g.Tools.putendopin,'endopin'); - g.iconcallbackhelper(g.Tools.putepipin,'epipin'); - g.iconcallbackhelper(g.Tools.interpendo,'interpendo'); - g.iconcallbackhelper(g.Tools.interpepi,'interpepi'); - - g.iconcallbackhelper(g.Tools.autolv,'autolv'); - set(g.Tools.refineendo, ... - 'Callback','lvpeter(''segmentrefineendo_Callback'',false,false)', ... - 'Interruptible','off','BusyAction','cancel'); - set(g.Tools.refineepi, ... - 'Callback','lvpeter(''segmentrefineepi_Callback'',false)', ... - 'Interruptible','off','BusyAction','cancel'); - set(g.Tools.expandendo, ... - 'Callback','lv(''segmentexpandcontract_Callback'',1,''endo'')',... - 'Interruptible','off','BusyAction','queue'); - set(g.Tools.contractendo, ... - 'Callback','lv(''segmentexpandcontract_Callback'',-1,''endo'')',... - 'Interruptible','off','BusyAction','queue'); - set(g.Tools.expandepi, ... - 'Callback','lv(''segmentexpandcontract_Callback'',1,''epi'')',... - 'Interruptible','off','BusyAction','queue'); - set(g.Tools.contractepi, ... - 'Callback','lv(''segmentexpandcontract_Callback'',-1,''epi'')',... - 'Interruptible','off','BusyAction','queue'); - set(g.Tools.propagateendo, ... - 'Callback','lvpeter(''segmentpropagateendo_Callback'')', ... - 'Interruptible','off','BusyAction','queue'); - set(g.Tools.propagateepi, ... - 'Callback','lvpeter(''segmentpropagateepi_Callback'')', ... - 'Interruptible','off','BusyAction','queue'); - %set(g.Tools.clearlv,'Callback','segmentation(''clearslices_Callback'',true,true,false,false)'); - - if not(strcmp(g.CurrentTheme, oldtheme)) - updatetool('drawendo'); - end - case 'rv' - g.CurrentTheme = 'rv'; - set(g.Handles.rightventriclepushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - g.Tools.interprvendo = g.iconcdatahelper(g.Handles.icon01,g.Icons.interprvendo,'Draw RV endocardium by point interpolation'); - g.Tools.rvendopen = g.iconcdatahelper(g.Handles.icon02,g.Icons.rvendopen,'Manually draw right ventricle endocardium'); - g.Tools.refinervendo = g.iconcdatahelper(g.Handles.icon03,g.Icons.refinervendo,'Refine RV endocardium (Ctrl-Alt-R)'); - g.Tools.putrvendopin = g.iconcdatahelper(g.Handles.icon04,g.Icons.putrvendopin,'Put endocardial pins that attracts the contour'); - g.Tools.interprvepi = g.iconcdatahelper(g.Handles.icon06,g.Icons.interprvepi,'Draw RV epicardium by point interpolation'); - g.Tools.rvepipen = g.iconcdatahelper(g.Handles.icon07,g.Icons.rvepipen,'Manually draw right ventricle epicardium'); - g.Tools.autorvendo = g.iconcdatahelper(g.Handles.icon12,g.Icons.autorvendo,'Auto segment RV endocardium (Ctrl-Alt-M)'); - g.Tools.clearrv = g.iconcdatahelper(g.Handles.icon15,g.Icons.trash,'Clear RV segmentation in selected slices'); - - g.iconcallbackhelper(g.Tools.rvendopen,'drawrvendo'); - g.iconcallbackhelper(g.Tools.rvepipen,'drawrvepi'); - g.iconcallbackhelper(g.Tools.putrvendopin,'rvendopin'); - g.iconcallbackhelper(g.Tools.interprvendo,'interprvendo'); - g.iconcallbackhelper(g.Tools.interprvepi,'interprvepi'); - - g.iconcallbackhelper(g.Tools.autorvendo,'autorvendo'); - %set(g.Tools.autorvepi,'Callback','lv(''segmentepi_Callback'',false,''rv'')');%finns - %�nnnu ej implementerad - set(g.Tools.refinervendo, ... - 'Callback','rv(''segmentrefinervendo_Callback''),false,false',... - 'Interruptible','off','BusyAction','cancel'); - set(g.Tools.clearrv,'Callback','segmentation(''clearslices_Callback'',false,false,true,true)'); - - if not(strcmp(g.CurrentTheme, oldtheme)) - updatetool('drawrvendo'); - end - case 'roi' - g.CurrentTheme = 'roi'; - set(g.Handles.roipushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - g.Tools.roipen = g.iconcdatahelper(g.Handles.icon01,g.Icons.roipen,'Manually draw/adjust ROI'); - g.Tools.putroi = g.iconcdatahelper(g.Handles.icon02,g.Icons.putroi,'Place a circular ROI'); - g.Tools.refineroi = g.iconcdatahelper(g.Handles.icon03,g.Icons.refineroi,'Refine ROI (Alt-R)'); - g.Tools.refineroinext = g.iconcdatahelper(g.Handles.icon04,g.Icons.refineroinext,'Propagate and refine ROI forward (Alt-F)'); - g.Tools.trackroi = g.iconcdatahelper(g.Handles.icon05,g.Icons.trackroi,'Track a vessel in all timeframes (Alt-T)'); - g.Tools.roicolor = g.iconcdatahelper(g.Handles.icon06,g.Icons.palette,'Color a ROI'); - g.Tools.roitext = g.iconcdatahelper(g.Handles.icon07,g.Icons.text,'Set ROI label'); - g.Tools.roiclear = g.iconcdatahelper(g.Handles.icon08,g.Icons.trash,'Remove ROI'); - - g.iconcallbackhelper(g.Tools.roipen,'drawroi'); - g.iconcallbackhelper(g.Tools.putroi,'putroi'); - - set(g.Tools.refineroi, ... - 'Callback','flow(''flowrefine_Callback'')',... - 'Interruptible','off','BusyAction','cancel'); - set(g.Tools.refineroinext, ... - 'Callback','flow(''flowpropagate_Callback'')',... - 'Interruptible','off','BusyAction','queue'); - g.iconcallbackhelper(g.Tools.trackroi,'trackroi');%set(g.Tools.trackroi,'Callback','flow(''flowtrackroi_Callback'')'); - set(g.Tools.roicolor,'Callback','roi(''roisetcolor_Callback'')'); - set(g.Tools.roitext,'Callback','roi(''roisetlabel_Callback'')'); - set(g.Tools.roiclear,'Callback','roi(''roidelete_Callback'')'); - - if not(strcmp(g.CurrentTheme, oldtheme)) - updatetool('drawroi'); - end - case 'scar' - g.CurrentTheme = 'scar'; - set(g.Handles.scarpushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - g.Tools.autoscar = g.iconcdatahelper(g.Handles.icon01,g.Icons.autoscar,'Automatically delineate scar regions'); - g.Tools.scarpen = g.iconcdatahelper(g.Handles.icon06,g.Icons.scarpen,'Manually add scar regions'); - g.Tools.mopen = g.iconcdatahelper(g.Handles.icon07,g.Icons.mopen,'Manually add region of microvascular obstruction'); - g.Tools.rubberpen = g.iconcdatahelper(g.Handles.icon08,g.Icons.rubberpen,'Manually remove scar regions'); - g.Tools.rubber = g.iconcdatahelper(g.Handles.icon09,g.Icons.rubber,'Draw to remove manual interaction'); - % g.Tools.scarundo = g.iconcdatahelper(g.Handles.icon10,g.Icons.undo,'Undo manual interaction'); - - g.iconcallbackhelper(g.Tools.autoscar,'autoscar');%set(g.Tools.autoscar,'Callback','viability(''viabilitycalc'');segment(''drawimageno'');'); - g.iconcallbackhelper(g.Tools.scarpen,'drawscar'); - g.iconcallbackhelper(g.Tools.mopen,'drawmo'); - g.iconcallbackhelper(g.Tools.rubberpen,'drawrubberpen'); - g.iconcallbackhelper(g.Tools.rubber,'drawrubber'); - - if not(strcmp(g.CurrentTheme, oldtheme)) - if isempty(SET(NO).Scar) - updatetool('select'); - else - updatetool('drawscar'); - end; - end; - case 'misc' - g.CurrentTheme = 'misc'; - set(g.Handles.annotationspushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - g.Tools.point = g.iconcdatahelper(g.Handles.icon01,g.Icons.point,'Place annotation point'); - g.Tools.measure = g.iconcdatahelper(g.Handles.icon02,g.Icons.measure,'Place measurement caliper'); - g.Tools.crop = g.iconcdatahelper(g.Handles.icon03,g.Icons.crop,'Crop image stack'); - g.Tools.autocropall = g.iconcdatahelper(g.Handles.icon04,g.Icons.autocropall,'Automatically crop all image stacks'); - g.Tools.flipx = g.iconcdatahelper(g.Handles.icon06,g.Icons.flipx,'Flip image stack in x and z direction'); - g.Tools.flipy = g.iconcdatahelper(g.Handles.icon07,g.Icons.flipy,'Flip image stack in y and z direction'); - %g.Tools.rotate90 = g.iconcdatahelper(g.Handles.icon08,g.Icons.rotate90,'Rotate image stack 90 degrees'); - g.Tools.click3d = g.iconcdatahelper(g.Handles.icon11,g.Icons.click3d,'Click image to show point in all views'); - g.iconcallbackhelper(g.Tools.point,'point'); - g.iconcallbackhelper(g.Tools.measure,'measure'); - g.iconcallbackhelper(g.Tools.crop,'crop'); - g.iconcallbackhelper(g.Tools.autocropall,'autocropall'); - g.iconcallbackhelper(g.Tools.click3d,'click3d'); - set(g.Tools.flipx,'Callback','tools(''flipx_Callback'')'); - set(g.Tools.flipy,'Callback','tools(''flipy_Callback'')'); - %set(g.Tools.rotate90,'Callback','segment(''toolsrotate90right_Callback'')'); - - if not(strcmp(g.CurrentTheme, oldtheme)) - updatetool('point'); - end - case 'view' - g.CurrentTheme = 'view'; - set(g.Handles.viewpushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - g.Tools.viewcine = g.iconcdatahelper(g.Handles.icon01,g.Icons.panel1,'View Cine images'); - g.Tools.viewcinescar = g.iconcdatahelper(g.Handles.icon02,g.Icons.row2,'View Cine and Scar'); - g.Tools.viewcinescarperf = g.iconcdatahelper(g.Handles.icon03,g.Icons.row3,'View Cine, Scar and Perfusion'); - g.Tools.viewstress = g.iconcdatahelper(g.Handles.icon04,g.Icons.row4,'View Stress'); - g.Tools.viewflow = g.iconcdatahelper(g.Handles.icon05,g.Icons.panel2,'View flow'); - set(g.Tools.viewcine,'Callback','segment(''viewspecial_Callback'',''cine'')'); - set(g.Tools.viewcinescar,'Callback','segment(''viewspecial_Callback'',''cinescar'')'); - set(g.Tools.viewcinescarperf,'Callback','segment(''viewspecial_Callback'',''cinescarperf'')'); - set(g.Tools.viewstress,'Callback','segment(''viewspecial_Callback'',''stress'')'); - set(g.Tools.viewflow,'Callback','segment(''viewspecial_Callback'',''flow'')'); - if not(strcmp(g.CurrentTheme, oldtheme)) - updatetool('select'); - end - case 'mar' - g.CurrentTheme = 'mar'; - set(g.Handles.marpushbutton,'backgroundcolor',g.GUISettings.ButtonSelectedColor); - g.Tools.marauto = g.iconcdatahelper(g.Handles.icon01,g.Icons.automar,'Automatically delineate MaR regions'); - g.Tools.marpen = g.iconcdatahelper(g.Handles.icon03,g.Icons.marpen,'Manually add MaR regions'); - g.Tools.marrubberpen = g.iconcdatahelper(g.Handles.icon04,g.Icons.rubberpen,'Manually remove MaR region'); - g.Tools.marrubber = g.iconcdatahelper(g.Handles.icon05,g.Icons.rubber,'Draw to remove manual interaction'); - - g.iconcallbackhelper(g.Tools.marauto,'automar');%set(g.Tools.marauto,'Callback','mar(''auto_Callback'');segment(''drawimageno'');'); - g.iconcallbackhelper(g.Tools.marpen,'drawmarpen'); - g.iconcallbackhelper(g.Tools.marrubberpen,'drawmarrubberpen'); - g.iconcallbackhelper(g.Tools.marrubber,'drawmarrubber'); - - if not(strcmp(g.CurrentTheme, oldtheme)) - updatetool('drawmarpen'); - end - end; - if (isequal(oldtheme,'scar')&¬(isequal(g.CurrentTheme,'scar')))||... - (isequal(oldtheme,'mar')&¬(isequal(g.CurrentTheme,'mar')))||... - isequal(g.CurrentTheme,'scar')||isequal(g.CurrentTheme,'mar') - drawfunctions('drawimageno'); - end - end - - %--------------------------------- - function updatetimethings(g,no,mode) %#ok - %--------------------------------- - %This fcn is called from switchimagestack and disables/enables - %features that are not available depending of the image stack is - %timeresolved or not. - %Overloaded in CVQgui. - global SET NO - -% if nargin==1 -% no = NO; -% end; - -% %Check if timeresolved -% if SET(no).TSize>1 -% set([g.Handles.mmodeviewicon],'enable','on'); -% set(g.Handles.volumeaxes,'visible','on'); -% set(g.Handles.flowaxes,'visible','on'); -% set(g.Handles.timebaraxes,'visible','on'); -% set([... -% g.Handles.playmovieicon ... -% g.Handles.playallicon ... -% g.Handles.nextframeicon ... -% g.Handles.nextallframeicon ... -% g.Handles.previousframeicon ... -% g.Handles.previousallframeicon ... -% g.Handles.fasterframerateicon ... -% g.Handles.slowerframerateicon ... -% g.Handles.cinetoolicon ... -% g.Handles.playmoviemenu ... -% g.Handles.stopmoviemenu ... -% g.Handles.reportslicemenu ... -% g.Handles.reportradvelmenu ... -% g.Handles.reportvolumecurvemenu],'enable','on'); -% else -% %No time, disable things -% set(g.Handles.volumeaxes,'Visible','off'); -% set(g.Handles.timebaraxes,'Visible','off'); -% set([... -% g.Handles.mmodeviewicon ... -% g.Handles.playmovieicon ... -% g.Handles.playallicon ... -% g.Handles.nextframeicon ... -% g.Handles.nextallframeicon ... -% g.Handles.previousframeicon ... -% g.Handles.previousallframeicon ... -% g.Handles.fasterframerateicon ... -% g.Handles.slowerframerateicon ... -% g.Handles.cinetoolicon ... -% g.Handles.playmoviemenu ... -% g.Handles.stopmoviemenu ... -% g.Handles.reportslicemenu ... -% g.Handles.reportradvelmenu ... -% g.Handles.reportvolumecurvemenu],'enable','off'); -% end; - - end - - %--------------------------------------- - function switchtoimagestack(g, no,force) - %--------------------------------------- - %This function makes no current image stack, and updates graphics. - global NO - - if g.Silent %&& not(force) %PH: - NO = no; - return; - end; - - %segment('updateviewicons',no); - - if isequal(NO,no)&&(nargin==2) - return; - end; - - if isequal(NO,no)&&(nargin==3) - if ~force - return; - end; - end; - - %--- Check if there are open report windows. - - %Check deleted windows - ind = true(1,length(g.BlockingFigs)); - for loop=1:length(ind) - try - get(g.BlockingFigs); - catch %#ok - ind(loop) = false; - end; - end; - - %Remove deleted windows - g.BlockingFigs = g.BlockingFigs(ind); - g.switchtoimagestack_part2(no); - - %Play again if play button is indented - stateandicon= segment('iconson','play'); - if stateandicon{1} - segment('playall_Callback'); - end - end - - - %-------------------------------------- - function drawroiinpanel(g,panel,docalc) - %-------------------------------------- - %Draw ROI's in one slice mode. - %Not overloaded anywhere. - global SET - - if nargin < 3 - docalc = true; - end - %First try to remove old ones - try - delete(g.Handles.roicontour{panel}); - delete(g.Handles.roitext{panel}); - catch %#ok - %do nothing if failed. - end - - %If flow then take ROI from flow. - no = g.ViewPanels(panel); - if ~isempty(SET(no).Parent) - no = SET(no).Parent; - end; - - % %Check on how many to plot - % ind=(SET(no).Roi(:).Z==SET(no).CurrentSlice); - % rois2plot = find(ind); - % numrois2plot = length(rois2plot); - % numrois=length(SET(no).RoiZ); - - - %Draw with no forces phase images to use from mag images - %if isequal(get(g.Handles.hideroiicon,'state'),'off') - %Plot them - g.Handles.roicontour{panel}= nan(1,SET(no).RoiN); - g.Handles.roitext{panel}= nan(1,SET(no).RoiN); - hold(g.Handles.imageaxes(panel),'on'); - for loop=1:SET(no).RoiN - if docalc - [~,area]=calcfunctions('calcroiarea',no,loop); - SET(no).Roi(loop).Area = area; - [m,sd]=calcfunctions('calcroiintensity',no,loop); - SET(no).Roi(loop).Mean = m; - SET(no).Roi(loop).StD = sd; - end - if SET(no).Roi(loop).Sign > 0 - roisign = ''; - else - roisign = ' (-)'; - end - %Input to force black background around corner text to improve visibility - if g.Pref.BackgroundColor - bgcolor = 'blue'; - else - bgcolor = 'none'; - end - g.Handles.roicontour{panel}(loop) = plot(g.Handles.imageaxes(panel),... - SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame),... - SET(no).Roi(loop).X(:,SET(no).CurrentTimeFrame),... - SET(no).Roi(loop).LineSpec); - [ymin,ix] = min(SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame)); - g.Handles.roitext{panel}(loop) = text(... - ymin-1,SET(no).Roi(loop).X(ix,SET(no).CurrentTimeFrame),... - {sprintf('%s%s',SET(no).Roi(loop).Name,roisign), ... - sprintf('%3.1f [cm^2]', ... - SET(no).Roi(loop).Area(SET(no).CurrentTimeFrame)), ... - sprintf('%3.1f ± %3.1f', ... - SET(no).Roi(loop).Mean(SET(no).CurrentTimeFrame), ... - SET(no).Roi(loop).StD(SET(no).CurrentTimeFrame))},... - 'HorizontalAlignment','right','VerticalAlignment','middle', ... - 'parent',g.Handles.imageaxes(panel),'backgroundcolor',bgcolor); - set(g.Handles.roitext{panel}(loop),'color',[1 1 1]); - if ~(ismember(SET(no).CurrentSlice,SET(no).Roi(loop).Z) && ... - ismember(SET(no).CurrentTimeFrame,SET(no).Roi(loop).T)) - set(g.Handles.roitext{panel}(loop),'Position',[nan nan]); - set(g.Handles.roicontour{panel}(loop),'XData',nan,'YData',nan); - end - end; - - %Width of ROI's - if g.Pref.LineWidth>0 - set(g.Handles.roicontour{panel},'linewidth',g.Pref.LineWidth); - set(g.Handles.roicontour{panel}(SET(no).RoiCurrent), ... - 'linewidth',g.Pref.LineWidth+1); - else - set(g.Handles.roicontour{panel},'visible','off'); - end; - - if isequal(get(g.Handles.hidetexticon,'state'),'on') - set(g.Handles.roitext{panel},'visible','off'); - end; - - hold(g.Handles.imageaxes(panel),'off'); - %else -% %Set up handles do not plot -% g.Handles.roicontour{panel} = zeros(1,SET(no).RoiN); -% hold(g.Handles.imageaxes(panel),'on'); -% g.Handles.roicontour{panel}(:) = plot(g.Handles.imageaxes(panel),NaN,NaN); -% hold(g.Handles.imageaxes(panel),'off'); -% end; -% - if ~isempty(g.FlowNO) && (no == g.FlowNO || ismember(g.FlowNO,SET(no).Linked)) && ~isempty(g.FlowROI) - if SET(no).RoiN <1 - g.FlowROI = []; - else - calcfunctions('calcflow',no); - end - end - g.updateaxestables('flow',no); - - end - - %----------------------------------- - function plotrois(g,panel,no,docalc) - %----------------------------------- - %Plot roi's if existing. Overloaded in CVQgui. - global DATA SET - - if nargin < 4 - docalc = true; - end - - %First try to remove old ones - try - delete(g.Handles.roicontour{panel}); - delete(g.Handles.roitext{panel}); - catch %#ok - %do nothing if failed. - end - - g.Handles.roicontour{panel} = nan(1,SET(no).RoiN); - g.Handles.roitext{panel} = []; - hold(g.Handles.imageaxes(panel),'on'); - for loop=1:SET(no).RoiN - xofs = SET(no).XSize*floor((round(SET(no).Roi(loop).Z)-1)/DATA.ViewPanelsMatrix{panel}(2)); - yofs = SET(no).YSize*mod(round(SET(no).Roi(loop).Z)-1,DATA.ViewPanelsMatrix{panel}(2)); - g.Handles.roicontour{panel}(loop) = plot(g.Handles.imageaxes(panel),... - SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame)+yofs,... - SET(no).Roi(loop).X(:,SET(no).CurrentTimeFrame)+xofs,... - SET(no).Roi(loop).LineSpec); - if docalc - [~,SET(no).Roi(loop).Area]=calcfunctions('calcroiarea',no,loop); - [m,sd]=calcfunctions('calcroiintensity',no,loop); - SET(no).Roi(loop).Mean = m; - SET(no).Roi(loop).StD = sd; - end - if g.Pref.LineWidth>0 - if ismember(loop,SET(no).RoiCurrent) - set(g.Handles.roicontour{panel}(loop),'linewidth',g.Pref.LineWidth+1); - else - set(g.Handles.roicontour{panel}(loop),'linewidth',g.Pref.LineWidth); - end - else - set(g.Handles.roicontour{panel}(loop),'visible','off'); - end; - end; - hold(g.Handles.imageaxes(panel),'off'); - end - - %------------------------------------------- - function segmentclearalllv_Callback(g,force) %#ok - %------------------------------------------- - %Clear all LV segmentation, both endo and epi - %Overloaded in CVQgui - - if nargin==1 - if ~yesno('Do you really want to remove all LV segmentation ?',[],g.GUI.Segment); - myfailed('Aborted by user.',g.GUI.Segment); - return; - end; - end; - - segmentation('clearalllv_Callback'); - end - - %------------------------------------------- - function segmentclearallrv_Callback(g,force) %#ok - %------------------------------------------- - %Clear all RV segmentation, both endo and epi - %Overloaded in CVQgui - - if nargin==1 - if ~yesno('Do you really want to remove all RV segmentation ?',[],g.GUI.Segment); - myfailed('Aborted by user.',g.GUI.Segment); - return; - end; - end; - - segmentation('clearallrv_Callback'); - end - - %----------------------------------------- - function segmentclearall_Callback(g,force) %#ok - %----------------------------------------- - %Clear all segmentation, both endo and epi, lv and rv mar and scar. - %Overloaded in CVQgui and RVQgui. - global SET NO - - if nargin==1 - msg='This removes all existing segmentation lv, rv, roi mar and scar. Are you sure?'; -% if isempty(SET(NO).Scar) -% msg='Do you really want to remove all segmentation (both LV and RV) ?'; -% else -% msg ='Do you really want to remove all segmentation (both LV, RV and Scar) ?'; -% end - if ~yesno(msg,[],g.GUI.Segment); - myfailed('Aborted by user.',g.GUI.Segment); - return; - end; - end; - - viability('viabilityclear_Callback'); - roi('roiclearall_Callback') - segmentation('clearall_Callback'); - mar('clearall_Callback'); - end - - %----------------------------------------------------- - function segmentclearallbutsystolediastole_Callback(g) - %----------------------------------------------------- - %Clears all segmentation in all timeframes but systole and diastole. - global SET NO - - if SET(NO).TSize<2 - myfailed('Not timeresolved data, aborting.',g.GUI.Segment); - return; - end; - - if isequal(SET(NO).EDT,SET(NO).EST) - myfailed('Systole and diastole occurs at the same time frame, aborting.',g.GUI.Segment); - return; - end; - - segmentation('removeallpins_Callback',true); %side effect calls enableundo - %Create index structure - ind = true(1,SET(NO).TSize); - ind(SET(NO).EDT) = false; - ind(SET(NO).EST) = false; - arg = struct('endo',true,'epi',true,'rvendo',true,'rvepi',true); - indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); - segmentation('removeallinterp_Callback',true,[],arg,indarg); - - if ~isempty(SET(NO).EndoX) - SET(NO).EndoX(:,ind,:) = NaN; - SET(NO).EndoY(:,ind,:) = NaN; - end; - - if ~isempty(SET(NO).EpiX) - SET(NO).EpiX(:,ind,:) = NaN; - SET(NO).EpiY(:,ind,:) = NaN; - end; - - if ~isempty(SET(NO).RVEndoX) - SET(NO).RVEndoX(:,ind,:) = NaN; - SET(NO).RVEndoY(:,ind,:) = NaN; - end; - - if ~isempty(SET(NO).RVEpiX) - SET(NO).RVEpiX(:,ind,:) = NaN; - SET(NO).RVEpiY(:,ind,:) = NaN; - end; - - SET(NO).EndoDraged(ind,:) = false; - SET(NO).EpiDraged(ind,:) = false; - - segment('updatevolume'); - segment('updatemodeldisplay'); - drawfunctions('drawsliceno'); - end - - %------------------------------------------------------- - function segmentclearalllvbutsystolediastole_Callback(g) - %------------------------------------------------------- - %Clears all LV segmentation except in systole and diastole. - %Overloaded in CVQgui - global SET NO - - if SET(NO).TSize<2 - myfailed('Not timeresolved data, aborting.',g.GUI.Segment); - return; - end; - - if isequal(SET(NO).EDT,SET(NO).EST) - myfailed('Systole and diastole occurs at the same time frame, aborting.',g.GUI.Segment); - return; - end; - - segmentation('removeallpins_Callback',true,1,1,0,0); %side effect calls enableundo - %Create index structure - ind = true(1,SET(NO).TSize); - ind(SET(NO).EDT) = false; - ind(SET(NO).EST) = false; - arg = struct('endo',true,'epi',true,'rvendo',false,'rvepi',false); - indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); - segmentation('removeallinterp_Callback',true,[],arg,indarg); - - %Create index structure - ind = true(1,SET(NO).TSize); - ind(SET(NO).EDT) = false; - ind(SET(NO).EST) = false; - - if ~isempty(SET(NO).EndoX) - SET(NO).EndoX(:,ind,:) = NaN; - SET(NO).EndoY(:,ind,:) = NaN; - end; - - if ~isempty(SET(NO).EpiX) - SET(NO).EpiX(:,ind,:) = NaN; - SET(NO).EpiY(:,ind,:) = NaN; - end; - - SET(NO).EndoDraged(ind,:) = false; - SET(NO).EpiDraged(ind,:) = false; - - lvsegchanged = true; segment('updatevolume',lvsegchanged); - segment('updatemodeldisplay'); - drawfunctions('drawsliceno'); - - end - - %------------------------------------------------------- - function segmentclearallrvbutsystolediastole_Callback(g) - %------------------------------------------------------- - %Clears all RV segmentation except in systole and diastole. - %Overloaded in CVQgui - global SET NO - - if SET(NO).TSize<2 - myfailed('Not timeresolved data, aborting.',g.GUI.Segment); - return; - end; - - if isequal(SET(NO).EDT,SET(NO).EST) - myfailed('Systole and diastole occurs at the same time frame, aborting.',g.GUI.Segment); - return; - end; - - segmentation('removeallpins_Callback',true,0,0,1,1); %side effect calls enableundo - %Create index structure - ind = true(1,SET(NO).TSize); - ind(SET(NO).EDT) = false; - ind(SET(NO).EST) = false; - arg = struct('endo',false,'epi',false,'rvendo',true,'rvepi',true); - indarg = struct('endoind',ind,'epiind',ind,'rvendoind',ind,'rvepiind',ind); - segmentation('removeallinterp_Callback',true,[],arg,indarg); - - if ~isempty(SET(NO).RVEndoX) - SET(NO).RVEndoX(:,ind,:) = NaN; - SET(NO).RVEndoY(:,ind,:) = NaN; - end; - - if ~isempty(SET(NO).RVEpiX) - SET(NO).RVEpiX(:,ind,:) = NaN; - SET(NO).RVEpiY(:,ind,:) = NaN; - end; - - SET(NO).EndoDraged(ind,:) = false; - SET(NO).EpiDraged(ind,:) = false; - - segment('updatevolume'); - segment('updatemodeldisplay'); - drawfunctions('drawsliceno'); - - end - - %--------------------------------- - function point_Buttondown(g,panel) - %--------------------------------- - %Button down function when point tool is active. - %Overloaded in CVQgui - global SET NO DATA - - if g.Interactionlock - return; - end; - - if any(strcmp(DATA.ViewPanelsType(DATA.CurrentPanel),{'trans3DP','sag3DP','cor3DP'})) - segment3dp.tools('click3dp_Callback',SET(NO).LevelSet.Pen.Color) - return - end - - segment('switchtopanel',panel); - no = NO; - - switch get(g.imagefig,'SelectionType') - - case 'alt' -% g.contextmenu; - [y,x,slice] = segment('getclickedcoords'); - ind = findfunctions('findclosestannotationpoint',x,y,slice); - - SET(NO).Point.X(ind)=x; - SET(NO).Point.Y(ind)=y; - SET(NO).Point.Z(ind)=slice; - - drawfunctions('drawimageno'); - case 'normal' - - %Use to point to mag data set - if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; - end; - - [x,y,slice] = segment('getclickedcoords'); - % If slice has changed, make sure montage/one are in sync - if (slice>SET(no).ZSize) - return; - end - segment('switchtoslice',slice); - - placetimeresolved = isequal(get(DATA.Handles.placetimeresolvedpoints,'checked'),'on'); - - if isempty(SET(no).Point) - annotationpoint('pointclearall'); % calls enableundo - else - tools('enableundo',no); - end; - - set(g.Handles.hidepointsicon,'state','off'); - - if (~placetimeresolved) || isempty(SET(no).Point) || (isempty(SET(no).Point.Label)) - %Ask for name if not placetimeresolved or first point - menuitems = {... - 'Apex',... - 'RV insertion',... - 'RV insertion Anterior',... - 'RV insertion Inferior',... - 'AV plane',... - 'TV plane',... - 'P1',... - 'P2',... - 'General',... - 'Sector start',... - 'User defined ...'}; - - c = mymenu('Name point',menuitems,g.GUI.Segment); - if c<1 - return; - end; - if c <=( length(menuitems)-1) - s = menuitems{c}; - else - - %last is User defined. - if c == (length(menuitems)) - s = inputdlg({'Enter name'},'Name',1,{sprintf('Point_%d',length(SET(no).Point.X))}); - if isempty(s) - myfailed('Invalid name.',g.GUI.Segment); - return; - end; - end; - end; - else - s = SET(no).Point.Label{end}; %Instead take name from last point - end; - - if isfield(SET(no).StrainTagging,'LVupdated') && strcmp(s,'AV plane') - SET(no).StrainTagging.LVupdated=1; - end - tvplanebool=strcmp(SET(no).Point.Label,'TV plane'); - if strcmp(s,'TV plane') && sum(tvplanebool)==2 - ind=find(tvplanebool,1); - SET(no).Point.X(ind)=[]; - SET(no).Point.Y(ind)=[]; - SET(no).Point.T(ind)=[]; - SET(no).Point.Z(ind)=[]; - SET(no).Point.Label(ind)=[]; - end - - SET(no).Point.X = [SET(no).Point.X y]; - SET(no).Point.Y = [SET(no).Point.Y x]; - SET(no).Point.T = [SET(no).Point.T NaN]; %Default non time resolved. - SET(no).Point.Z = [SET(no).Point.Z SET(no).CurrentSlice]; - SET(no).Point.Label = [SET(no).Point.Label s]; - - drawfunctions('drawimageno'); - - %If placetimeresolved option is enable then show this in this frame - %only. - if placetimeresolved - g.pointshowthisframeonly_Callback; - end; - - end - - %If straintagging initiated adjust LVupdated - if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') - SET(no).StrainTagging.LVupdated = 1; - end - - datacursormode off; - end; %end of point_Buttondown; - - %----------------------------------------- - function measurerenamethis_Callback(g,arg) - %----------------------------------------- - %Rename current measurement. - %Overloaded in CVQgui. - global SET NO - - ask = false; - if nargin > 1 && strcmp(arg,'ask') - ask = true; - end - - %Use to point to mag data set - no = NO; - if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; - end; - - if isempty(SET(no).Measure) - myfailed('No measurement exist.'); - return; - end - - if ask && length(SET(no).Measure) > 1 - m = mymenu('Select measurement',... - {SET(no).Measure.LongName},g.GUI.Segment); - if m > 0 - g.MeasureN = m; - else - return - end - end - - n = g.MeasureN; - if (length(SET(no).Measure) 1 && strcmp(arg,'ask') - ask = true; - end - - %Use to point to mag data set - no = NO; - if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; - end; - - if isempty(SET(no).Measure) - myfailed('No measurement exist.'); - return; - end - - if ask && length(SET(no).Measure) > 1 - m = mymenu('Select measurement',... - {SET(no).Measure.LongName},g.GUI.Segment); - if m > 0 - g.MeasureN = m; - else - return - end - end - - n = g.MeasureN; - if (length(SET(no).Measure) roicontext -% set(g.Handles.lvcontextmenu,... -% 'Position',p,'Visible','on'); -% case 'rv' -% set(g.Handles.rvcontextmenu,... -% 'Position',p,'Visible','on'); -% case 'scar' -% set(g.Handles.scarcontextmenu,... -% 'Position',p,'Visible','on'); -% case 'misc' -% % In Segment, all cases leading to misc are handled above -% % Can get here in specialGUI. -% set(g.Handles.annocontextmenu,... -% 'Position',p,'Visible','on'); -% -% -% end - end - - %------------------------- - function setprefhandles(g) - %------------------------- - %Called by segpref (main). Overloaded in CVQgui since uses another fig - %Also overloaded in Segment CMR and Segment CT - figname = 'segpref'; - fig = openfig(figname,'reuse'); - set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); %g.GUISettings.BackgroundColor); % - - % Generate a structure of handles to pass to callbacks, and store it. - g.PrefHandles = guihandles(fig); - g.PrefHandles.fig = fig; - - end - - %---------------------------- - function updateprefhandles(g) - %---------------------------- - %Updates PrefHandles. Called by segpref('update') - %Overloaded in CVQgui and RVQgui. - %Default folder locations - set(g.PrefHandles.datapathtext,'String',g.Pref.datapath); - set(g.PrefHandles.exportpathtext,'String',g.Pref.exportpath); - set(g.PrefHandles.cdpathtext,'String',g.Pref.CDPath); - - %Drawing/Viewing - set(g.PrefHandles.addpointscheckbox,'Value',g.Pref.AddPoints); - set(g.PrefHandles.blackwhitecheckbox,'Value',g.Pref.BlackWhite); - set(g.PrefHandles.linewidthedit,'String',sprintf('%0.5g',g.Pref.LineWidth)); - set(g.PrefHandles.markersizeedit,'String',sprintf('%0.5g',g.Pref.MarkerSize)); - set(g.PrefHandles.contouradjustdistanceedit,'String',sprintf('%0.5g',g.Pref.ContourAdjustDistance)); - set(g.PrefHandles.numpointsedit,'String',sprintf('%d',g.Pref.NumPoints)); - set(g.PrefHandles.numpointstext,'String',sprintf('%d',g.NumPoints)); - set(g.PrefHandles.interppointsedit,'String',sprintf('%d',g.Pref.NumInterpPoints)); - set(g.PrefHandles.numberthumbnailsedit,'String',sprintf('%0.5g',g.Pref.NumberVisibleThumbnails)); - set(g.PrefHandles.anonymcheckbox,'Value',g.Pref.AnonymMode); - set(g.PrefHandles.viewinterpolatedcheckbox,'Value',g.Pref.ViewInterpolated); - set(g.PrefHandles.bgcolorcheckbox,'Value',g.Pref.BackgroundColor); - - switch g.Pref.GUIBackgroundColor(1) - case 0.94 - set(g.PrefHandles.backgroundcolorpopupmenu,'Value',1); - case 0.34 - set(g.PrefHandles.backgroundcolorpopupmenu,'Value',2); - case 0 - set(g.PrefHandles.backgroundcolorpopupmenu,'Value',3); - end - - %Analysis - set(g.PrefHandles.endocenterradiobutton,'Value',g.Pref.EndoCenter); - set(g.PrefHandles.epicenterradiobutton,'Value',not(g.Pref.EndoCenter)); - set(g.PrefHandles.radialprofilesedit,'String',sprintf('%d',g.Pref.RadialProfiles)); - set(g.PrefHandles.includeallpixelsinroicheckbox,'value',g.Pref.IncludeAllPixelsInRoi); - set(g.PrefHandles.uselightcheckbox,'Value',g.Pref.UseLight); - - %System - set(g.PrefHandles.hidefilesunixcheckbox,'Value',g.Pref.HideFilesUnix); % /JT ticket #412 - set(g.PrefHandles.showseriesdescriptioncheckbox, 'Value', g.Pref.ShowSeriesDescription); % /JT #411 - set(g.PrefHandles.donotaskcheckbox,'Value',g.Pref.DoNotAsk); - set(g.PrefHandles.fastpreviewloadcheckbox,'Value',g.Pref.FastPreviewLoad); - set(g.PrefHandles.checkversioncheckbox,'Value',g.Pref.CheckVersion); - set(g.PrefHandles.useproxyservercheckbox,'Value',g.Pref.UseProxyServer); - set(g.PrefHandles.openGLcheckbox,'Value',g.Pref.OpenGLSoftware); - set(g.PrefHandles.gpucheckbox,'Value',g.Pref.GPU.Use); - set(g.PrefHandles.checkboxaskaddcomment,'Value',g.Pref.AskAddComment); - - if isequal(g.Pref.WebBrowser,'explorer') - set(g.PrefHandles.webbrowserpopupmenu,'value',1); - elseif isequal(g.Pref.WebBrowser,[getenv('ProgramFiles') '\Mozilla Firefox\firefox.exe']); - set(g.PrefHandles.webbrowserpopupmenu,'value',2); - else - set(g.PrefHandles.webbrowserpopupmenu,'value',3); - end - end - - %------------------------------------ - function updateprefhandlesadvanced(g) - %------------------------------------ - %Called by segpref('updateadvanced'). Overloaded in SegmentGUI and - %RVQGUI. - - %DICOM COmmunication Settings - set(g.PrefHandlesAdvanced.imagebasepathtext,'String',g.Pref.Pacs.ImageBasePath); - set(g.PrefHandlesAdvanced.tempstoragepathtext,'String',g.Pref.Pacs.TempStoragePath); - set(g.PrefHandlesAdvanced.pafreportfoldertext,'String',g.Pref.Pacs.PAFPathname); - set(g.PrefHandlesAdvanced.reportfoldertext,'String',g.Pref.Pacs.ReportsheetPath); - set(g.PrefHandlesAdvanced.dicomportedit,'String',g.Pref.Server.DICOMPort); - set(g.PrefHandlesAdvanced.aetitleedit,'String',g.Pref.Server.AETitle); - set(g.PrefHandlesAdvanced.sendoptionsedit,'String',g.Pref.Pacs.SendOptions); - set(g.PrefHandlesAdvanced.switchtagscheckbox,'Value',g.Pref.Pacs.SwitchTags); - set(g.PrefHandlesAdvanced.receiveoptionsedit,'String',g.Pref.Server.ReceiveOptions); - - %DICOM Interpretation - set(g.PrefHandlesAdvanced.fasterpreviewcheckbox,'Value',g.Pref.Dicom.FasterPreview); - set(g.PrefHandlesAdvanced.force16bitcheckbox,'Value',g.Pref.Dicom.Force16Bit); - if isempty(g.Pref.Dicom.NormalizePhase) - set(g.PrefHandlesAdvanced.normalizephaseask,'Value',1); - set(g.PrefHandlesAdvanced.normalizephaseno,'Value',0); - set(g.PrefHandlesAdvanced.normalizephaseyes,'Value',0); - else - set(g.PrefHandlesAdvanced.normalizephaseask,'Value',0); - set(g.PrefHandlesAdvanced.normalizephaseno,'Value',~g.Pref.Dicom.NormalizePhase); - set(g.PrefHandlesAdvanced.normalizephaseyes,'Value',g.Pref.Dicom.NormalizePhase); - end - - set(g.PrefHandlesAdvanced.userloggingcheckbox,'Value',g.Pref.UserLogging); - val = mygetvalue(g.PrefHandlesAdvanced.userloggingcheckbox); - - if val==1 - set(g.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','on'); - else - set(g.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); - end - set(g.PrefHandlesAdvanced.userlogpathtext,'String',g.Pref.UserLogPath); - end - - %---------------------- - function defaultpref(g) - %---------------------- - %Sets Pref to default values. Called by segpref('default_Callback') - %Overloaded in CVQgui, RVQgui, Segment CMRgui. - - %fodle location - g.Pref.datapath = pwd; - g.Pref.exportpath = pwd; - g.Pref.CDPath = 'F:'; - - %drawing/viewing - g.Pref.AddPoints = false; - g.Pref.BlackWhite = false; - g.Pref.LineWidth = 1; - g.Pref.MarkerSize = 5; - g.Pref.ContourAdjustDistance = 3; - g.Pref.NumPoints = 80; - g.Pref.NumInterpPoints = 15; - g.Pref.NumberVisibleThumbnails = 7; - g.Pref.AnonymMode = false; - g.Pref.ViewInterpolated = false; - g.Pref.UserLogging=0; - g.Pref.UserLogPath=[]; - - %Analysis - g.Pref.EndoCenter = true; - g.Pref.RadialProfiles = 80; - g.Pref.IncludeAllPixelsInRoi = false; - g.Pref.UseLight = false; - - %System - g.Pref.HideFilesUnix = true; - g.Pref.AllowDicomCache = 0; - g.Pref.ShowSeriesDescription = false; - g.Pref.DoNotAsk = false; - g.Pref.WebBrowser = 'explorer'; - g.Pref.FastPreviewLoad = true; - g.Pref.CheckVersion = true; - - %Communication - g.Pref.Server.ReceiveOptions = ''; %'--prefer-little'; %This is used for storescp to configure. - g.Pref.Pacs.SendOptions = ''; %This is used for storescu to configure. - % g.Pref.LearnMode = false; - % g.Pref.UndoHistory = 10; - % g.Pref.AutoSave = false; - end - - %------------------------------- - function normalizephaseupdate(g) - %------------------------------- - %Called by segpref.m methods - %Overloaded in CVQgui (different handle placement) - handle = g.PrefHandlesAdvanced; - - if isempty(g.Pref.Dicom.NormalizePhase) - set(handle.normalizephaseask,'Value',1); - set(handle.normalizephaseno,'Value',0); - set(handle.normalizephaseyes,'Value',0); - else - set(handle.normalizephaseask,'Value',0); - set(handle.normalizephaseno,'Value',~g.Pref.Dicom.NormalizePhase); - set(handle.normalizephaseyes,'Value',g.Pref.Dicom.NormalizePhase); - end - end - - %----------------------------------- - function varargout = initopenfile(g) - %----------------------------------- - %Initializes the openfile GUI. Optional output is the fig - %Called by openfile (main). Overloaded in CVQgui - if isopengui('openfile.fig') - openfile('exitgui') - end - g.GUI.OpenFile = mygui('openfile.fig'); - fig=g.GUI.OpenFile.fig; - gui=g.GUI.OpenFile; - - % Use system color scheme for figure: - set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); %g.GUISettings.BackgroundColor); % - - % Generate a structure of handles to pass to callbacks, and store it. - g.Preview.Handles = g.GUI.OpenFile.handles; %guihandles(fig); - g.Preview.Handles.fig = fig; - g.Preview.Silent = false; - g.Preview.CanCrop = false; - - %Horisonal adjustment - set(fig,'units','pixels'); - - load('newicons.mat','newicons') - gui.Icons=newicons; - gui.iconholder = myiconplaceholder(gui.handles.iconaxes,0,3,fig); - openfile('initiconholder'); - set(gui.fig,'WindowButtonMotionFcn','openfile(''motionfunc'')'); -% %Add some images -% load('icons.mat') -% set(g.Preview.Handles.browsepushbutton,'CData',icon.opendoc); -% set(g.Preview.Handles.updirpushbutton,'CData',icon.updir); -% set(g.Preview.Handles.refreshpushbutton,'CData',icon.refresh); - - %Fix with preview axis - try - axes(g.Preview.Handles.previewaxes); - catch %#ok - g.Preview.Handles.previewaxes = gca; - end; - g.Preview.Handles.image = image(repmat(0,[1 1 3])); - g.Preview.PreviewFile = ''; - axis off; - - %Check directory and fill pathlistbox - if ~exist(g.Preview.PathName,'dir') - g.Preview.PathName = pwd; - openfile('browsebutton_Callback'); - end; - - %set(g.Preview.Handles.fig,'keypressfcn',@keypressed); - %set(g.Preview.Handles.pathlistbox,'keypressfcn',@keypressed); - - %Scans directory and update lister - openfile('getpathinfo'); %Updates g.Preview.FileList - if length(g.Preview.PathName)>130 - set(g.Preview.Handles.pathtext,'String',['... ' g.Preview.PathName((end-130):end)]); - else - set(g.Preview.Handles.pathtext,'String',g.Preview.PathName); - end; - - [types,viewplanes,techniques] = g.imagedescription; - g.ImageTypes = types; - g.ImageViewPlanes = viewplanes; - g.ImagingTechniques = techniques; - if isfield(g.Preview.Handles,'imagingtechniquelistbox') - set(g.Preview.Handles.imagingtechniquelistbox,'String',techniques); - set(g.Preview.Handles.imagetypelistbox,'String',types); - set(g.Preview.Handles.imageviewplanelistbox,'String',viewplanes); - end - - g.Preview.ImageType = 'General'; - g.Preview.ImageViewPlane = 'Unspecified'; - g.Preview.ImagingTechnique = 'Unspecified'; - - %Update region of interrest selection button. - openfile('roisizelistbox_Callback', g.Preview.ROISize); - - %Update stable selection - %set(g.Preview.Handles.stablecheckbox,'value',double(g.Preview.Stable)); - - if nargout > 0 - varargout{1} = fig; - end - - end - - %------------------------- - function enableopenfile(g) - %------------------------- - %Called by openfile('enablesegmentgui'). Overloaded in CVQgui and RVQgui. - - if any(strcmp(g.ProgramName,{'Segment 3DPrint'})) - set([g.Handles.pointsmenu g.Handles.threedpmenu], 'enable','on') - end - if any(strcmp(g.ProgramName,{'Segment CT'})) - set([g.Handles.pointsmenu], 'enable','on') - end - -set([... %g.Handles.reportmenu ... g.Handles.t2starmenu ...g.Handles.t1analysismenu ...g.Handles.t2analysismenu ... - g.Handles.measuremenu ... - g.Handles.fileloadnextmenu ... - g.Handles.toolsmenu ... - g.Handles.roimenu ... - g.Handles.editmenu ... - g.Handles.exportmenu ... - g.Handles.segmentmenu ... - g.Handles.mrmenu ... - g.Handles.viabilitymenu ... - g.Handles.flowmenu ... - g.Handles.ctmenu ... - g.Handles.spectmenu ... - g.Handles.viewmenu ... - g.Handles.lvmenu ... - g.Handles.rvmenu ... - g.Handles.analysismenu ... - g.Handles.fileloadsegmentationmenu ... - g.Handles.fileloadnextmenu ... - g.Handles.filesavesegmentationmenu ... - g.Handles.filesavesubmenu ... - g.Handles.filesavecurrentmenu ... - g.Handles.filesaveallmenu ... - g.Handles.filesaveallasmenu ... - g.Handles.filesavetodatabasemenu ... - g.Handles.filesavetopacsmenu ... - g.Handles.filesavesegdicom ... - g.Handles.fileclosecurrentimagestack ... - g.Handles.filecloseallmenu ... - g.Handles.fileclosemultiplemenu ... - g.Handles.thumbnailslider... - ],... - 'enable','on'); - - set([... - g.Handles.reportpanel ... - g.Handles.barpanel ... %g.Handles.thistimeframeonlycheckbox ...%g.Handles.excludepapilarscheckbox ...%g.Handles.uselightcheckbox ... - ],...%g.Handles.thumbnailslider... - 'visible','on'); - - end - - %----------------------- - function checkversion(g) %#ok - %----------------------- - %Check if new version is available. Define separately for each GUI. - end - - %------------------------------------------ - function updateaxestables(g, arg, varargin) %#ok - %------------------------------------------ - %Method to update AxesTables, in GUIs where present - end - - %-------------------------------- - function roiputroi_helper(g,no,m) - %-------------------------------- - %Called by roi('roiputroi_Buttondown') - %Overloaded in CVQgui and RVQgui - global SET DATA - - oldpref=DATA.ThisFrameOnly; - - if ~isempty(SET(no).Flow) - DATA.ThisFrameOnly = false; - end - - [y,x,slice] = segment('getclickedcoords'); - - o = linspace(0,2*pi,g.NumPoints)'; - SET(no).Roi(m).X = min(SET(no).XSize+0.5,max(0.5,... - repmat(x+8*sin(o),1,SET(no).TSize) )); - SET(no).Roi(m).Y = min(SET(no).YSize+0.5,max(0.5,... - repmat(y+8*cos(o),1,SET(no).TSize) )); - - %Find name - if SET(no).RoiN==1 || isempty(SET(no).RoiCurrent) - if isequal(SET(no).ImageViewPlane,'Aorta') - SET(no).Roi(m).Name = 'Aortic ascending flow'; - else - tempN = SET(no).RoiN; while ismember(sprintf('ROI-%d',tempN),{SET(no).Roi(1:end-1).Name}), tempN = tempN+1; end - SET(no).Roi(m).Name = sprintf('ROI-%d',tempN); - end; - SET(no).Roi(m).LineSpec = 'b-'; - else - if length(SET(no).Roi(SET(no).RoiCurrent(end)).Name)>=4 && isequal(SET(no).Roi(SET(no).RoiCurrent(end)).Name(1:4),'ROI-') - tempN = SET(no).RoiN; while ismember(sprintf('ROI-%d',tempN),{SET(no).Roi(1:end-1).Name}), tempN = tempN+1; end - SET(no).Roi(m).Name = sprintf('ROI-%d',tempN); - else - SET(no).Roi(m).Name =SET(no).Roi(SET(no).RoiCurrent(end)).Name; - end - SET(no).Roi(m).LineSpec = SET(no).Roi(SET(no).RoiCurrent(end)).LineSpec; - end; - - if g.ThisFrameOnly - SET(no).Roi(m).T = SET(no).CurrentTimeFrame; - else - SET(no).Roi(m).T = 1:SET(no).TSize; - end - SET(no).Roi(m).Z = slice; - SET(no).Roi(m).Sign = 1; - %SET(no).Roi(m).LineSpec = g.GUISettings.DefaultROISpec; - - %define if ROI should updated flow result - if ~isempty(SET(no).Flow) - SET(no).Roi(m).Flow = true; - else - SET(no).Roi(m).Flow = false; - end - - %Make as current - SET(no).RoiCurrent = m; - - if oldpref~=DATA.ThisFrameOnly; - DATA.ThisFrameOnly=oldpref; - end - end - - %-------------------------------------------------- - function name = roilabelmenu(g,roitoname,roinamein) - %-------------------------------------------------- - %Prompt name of ROI from a menu selection - %Overloaded in CVQ and RVQ - - global SET - - name = ''; - - useroinname=true; - if nargin < 2 || isempty(roitoname) - useroinname=false; - end - - temp = {... - 'Papillary',... - 'Remote ROI',... - 'Scar region ROI',... - 'Static tissue',... - 'Non-static tissue',... - 'Aortic ascending flow',... - 'Aortic descending flow',... - 'Abdominal Aorta',... - 'Pulmonary artery',... - 'Vena cava inf',... - 'Vena cava sup',... - 'ULPV', ... - 'LLPV', ... - 'URPV', ... - 'LRPV', ... - 'LPA', ... - 'RPA', ... - 'Sinus coronarius',... - 'Lung',... - 'Heart',... - 'Blood',... - 'Aortic valve',... - 'Pulmonary valve',... - 'Mitral valve',... - 'Tricuspid valve',... - 'Left atrium',... - 'Right atrium',... - 'Left ventricle',... - 'Right ventricle',... - 'Coronary sinus rest',... - 'Coronary sinus stress'}; - - no=roi('roifindmag'); - - if SET(no).RoiN>0 - roinames=cell(1,SET(no).RoiN); - for rloop=1:SET(no).RoiN - roinames{rloop}=SET(no).Roi(rloop).Name; - end - temp = cat(2,union(temp,roinames)); - end; - - if useroinname - temp = cat(2,'User defined ...','ROI-n',temp); - else - temp = cat(2,'User defined ...',temp); - end - - if nargin<3 - m = mymenu('Select a name',temp,g.GUI.Segment); - else - m = mymenu(strcat([translation.dictionary('Select a new name for "') roinamein '"']),temp,g.GUI.Segment); - end - - if useroinname - if m==1 - if iscell(roitoname) - name = inputdlg({'Enter name for ROI'},... - 'New name',... - 1,... - {'ROI'}); - else - name = inputdlg({'Enter name for ROI'},... - 'New name',... - 1,... - {sprintf('ROI-%d',roitoname)}); - end - if isempty(name) - name = sprintf('ROI-%d',roitoname); - else - name = name{1}; - end; - end; - - if m==2 - if iscell(roitoname) - for loop = 1:length(roitoname) - name{loop}=sprintf('ROI-%d',roitoname{loop}); - end - else - name = sprintf('ROI-%d',roitoname); - end - end; - - if m>2 - name = temp{m}; - end; - else - if m==1 - name = inputdlg({'Enter name for ROI'},... - 'New name',... - 1,... - {'ROI'}); - if isempty(name) - name = 'ROI'; - else - name = name{1}; - end; - end; - - if m>1 - name = temp{m}; - end; - end - - end - - %---------------------------- - function updatetimebaraxes(g) - %---------------------------- - %update time bar axes in main interface - global DATA SET NO - - if ~isempty(DATA.FlowNO) && ismember(NO,SET(DATA.FlowNO).Linked) - no = DATA.FlowNO; - else - no = NO; - end - - if isempty(no) || SET(no).TSize<2 - cla(g.Handles.timebaraxes); - set(g.Handles.timebaraxes,'Visible','off') - g.Handles.timebar = []; - g.Handles.timebaraxeshelpers=[]; - g.Handles.edtimebartext=[]; - g.Handles.estimebartext=[]; - g.Handles.edtimebarline=[]; - g.Handles.estimebarline=[]; - else - - set(g.Handles.timebaraxes,'Visible','on') - %this is speed problem ... try to fix by checking if - lc = DATA.GUISettings.BarColor;%[55 119 106]/255; %[1 0.47 0]; %[1 0.6 0.2]; % [0.5 0.5 0]; %JU - t = SET(no).TimeVector*1000; - if ~isfield(g.Handles,'timebar') || isempty(g.Handles.timebar) - g.Handles.timebar = plot(g.Handles.timebaraxes,... - [t(SET(no).CurrentTimeFrame) t(SET(no).CurrentTimeFrame)],... - get(g.Handles.timebaraxes,'ylim'),'-','Color',lc); - set(g.Handles.timebar,'linewidth',3); - else - set(g.Handles.timebar,'xdata',[t(SET(no).CurrentTimeFrame) t(SET(no).CurrentTimeFrame)],'color',lc); - end - hold(g.Handles.timebaraxes,'on'); - temp = get(g.Handles.timebaraxes,'ylim'); - ttemp = [t;t]; - temp = [repmat(temp(1),size(t));repmat(temp(1)+0.1*(temp(2)-temp(1)),size(t))]; - - if length(g.Handles.timebaraxeshelpers)~=length(t) - delete(g.Handles.timebaraxeshelpers) - g.Handles.timebaraxeshelpers=[]; - end - - if ~isfield(g.Handles,'timebaraxeshelpers') || isempty(g.Handles.timebaraxeshelpers) - g.Handles.timebaraxeshelpers=plot(g.Handles.timebaraxes,ttemp,temp,'k-'); - set(g.Handles.timebaraxes,'YTick',[]); - else - instr=ones(1,length(t)); - xcell=mat2cell(ttemp,2,instr)'; - ycell=mat2cell(temp,2,instr)'; - set(g.Handles.timebaraxeshelpers,{'XData'},xcell,{'YData'},ycell) - end - - set(g.Handles.timebaraxes,'ButtonDownFcn','segment(''timebaraxes_Buttondown'')'); - - %ED and ES - temp = get(g.Handles.timebaraxes,'ylim'); - tempmax = temp(end); %JU - tempmin = temp(1); %JU - - if ~isfield(g.Handles,'edtimebartext') || isempty(g.Handles.edtimebartext) - g.Handles.edtimebartext = text(... - 'position',[t(SET(no).EDT)-t(end)*0.015 tempmax-0.2*(tempmax-tempmin)],... - 'string','ED',... - 'parent',g.Handles.timebaraxes,... - 'color',lc, ... - 'FontWeight','bold'); - else - set(g.Handles.edtimebartext,'position',[t(SET(no).EDT)-t(end)*0.015 tempmax-0.2*(tempmax-tempmin)],'color',lc) - end - - if ~isfield(g.Handles,'edtimebarline') || isempty(g.Handles.edtimebarline) - g.Handles.edtimebarline = plot(g.Handles.timebaraxes,... - [t(SET(no).EDT) t(SET(no).EDT)],[tempmax tempmax*0.8],'color',lc); - else - set(g.Handles.edtimebarline,'xdata',[t(SET(no).EDT) t(SET(no).EDT)],'ydata',[tempmax tempmax*0.8],'color',lc); - end - - set([g.Handles.edtimebartext g.Handles.edtimebarline],'ButtonDownFcn','segment(''esedtimebar_Buttondown'',''ed'')','color',lc); - - if ~isfield(g.Handles,'estimebartext') || isempty(g.Handles.estimebartext) - g.Handles.estimebartext = text(... - 'parent',g.Handles.timebaraxes,... - 'position',[t(SET(no).EST)-0.015*t(end) tempmin+0.2*(tempmax-tempmin)],... - 'string','ES',... - 'color',lc, ... - 'FontWeight','bold'); - else - set(g.Handles.estimebartext,'position',[t(SET(no).EST)-0.015*t(end) tempmin+0.2*(tempmax-tempmin)],'color',lc) - end - - if ~isfield(g.Handles,'estimebarline') || isempty(g.Handles.estimebarline) - g.Handles.estimebarline = plot(g.Handles.timebaraxes,[t(SET(no).EST) t(SET(no).EST)],... - [tempmin tempmin+(0.2*(tempmax-tempmin))],'color',lc); - else - set(g.Handles.estimebarline,'xdata',[t(SET(no).EST) t(SET(no).EST)],'ydata',[tempmin tempmin+(0.2*(tempmax-tempmin))],'color',lc); - end - - - hold(g.Handles.timebaraxes,'off'); - set([g.Handles.estimebartext g.Handles.estimebarline],'ButtonDownFcn','segment(''esedtimebar_Buttondown'',''es'')'); - set(g.Handles.timebar,'buttondownFcn','segment(''timebar_Buttondown'')'); - set(g.Handles.timebaraxes,'xlim',[t(1) t(end)]); - - xlabel(g.Handles.timebaraxes,translation.dictionary('Time [ms]'),'color',g.GUISettings.TimebarAxesColor); - set(g.Handles.timebaraxes,... - 'XColor',g.GUISettings.TimebarAxesColor,... - 'YColor',g.GUISettings.TimebarAxesColor); - set(g.Handles.timebaraxes, ... - 'Color',g.GUISettings.VolumeColorGraph); - - if any(no == DATA.LVNO) - set(DATA.Handles.timebarlv,'xdata',... - t(SET(no).CurrentTimeFrame)*[1 1]) - end - if no == DATA.FlowNO - set(DATA.Handles.timebarflow,'xdata',... - t(SET(no).CurrentTimeFrame)*[1 1]) - end - end - end - - - %--------------------------- - function updatevolumeaxes(g) - %--------------------------- - %Called by segment_main('updatevolume'). - global DATA SET - - if ~isempty(DATA.LVNO) - no = DATA.LVNO(1);%first works as this is general for all lax stacks. - elseif ~isempty(DATA.RVNO) - no = DATA.RVNO; - else - no = []; - end - - if isempty(no) || SET(no).TSize<2 - cla(g.Handles.volumeaxes); - g.Handles.timebarlv = []; - g.Handles.volumecurve = []; - g.Handles.masscurve = []; - g.Handles.rvvcurve = []; - g.Handles.volumeaxeshelpers = []; - g.Handles.estext=[]; - g.Handles.edtext=[]; - g.Handles.esline=[]; - g.Handles.edline=[]; - g.Handles.lvmtext=[]; - set(g.Handles.volumeaxes,'Visible','off'); - else - lc = DATA.GUISettings.BarColor;%[55 119 106]/255; - set(g.Handles.volumeaxes,'Visible','on'); - %LV and RV curve and lines - t = SET(no).TimeVector*1000; - oldvolpeak=0; - oldrvpeak=0; - ylim(g.Handles.volumeaxes,'auto') - - %This tells us if bar removal is needed. Needed being that if masscurve max is changed or the borders have changed - if ~isempty(g.Handles.masscurve) - %oldlvm=max(get(g.Handles.masscurve,'ydata')); - end - yborders=get(g.Handles.volumeaxes,'ylim'); - yroofprecurves=yborders(2); - - if isempty(g.Handles.volumecurve)||~ishandle(g.Handles.volumecurve) - g.Handles.volumecurve = plot(g.Handles.volumeaxes,t,SET(no).LVV-SET(no).PV,'r.-'); - set(g.Handles.volumecurve,'markersize',5); - else - oldvolpeak=max(get(g.Handles.volumecurve,'ydata')); - set(g.Handles.volumecurve,'xdata',t,'ydata',SET(no).LVV-SET(no).PV) - end - - newvolpeak=max(get(g.Handles.volumecurve,'ydata')); - hold(g.Handles.volumeaxes,'on'); - lvmplot = SET(no).EPV-SET(no).LVV+SET(no).PV; - if sum(~isnan(lvmplot)) == length(lvmplot) - linespec = 'b-'; - markersize = 3; - else - linespec = 'b.-'; - markersize = 5; - end - - if isempty(g.Handles.masscurve) || ~ishandle(g.Handles.masscurve) - g.Handles.masscurve = plot(g.Handles.volumeaxes,t,lvmplot,linespec); - set(g.Handles.masscurve,'markersize',markersize); - else - set(g.Handles.masscurve,'xdata',t,'ydata',lvmplot) - end - - if isempty(g.Handles.rvvcurve) || ~ishandle(g.Handles.rvvcurve) - %if ~isfield(g.Handles,'rvvcurve') || isempty(g.Handles.rvvcurve) - % if ishandle(g.Handles.rvvcurve) - g.Handles.rvvcurve = plot(g.Handles.volumeaxes,t,SET(no).RVV,'m.-'); - set(g.Handles.rvvcurve,'markersize',5); - - else - oldrvpeak=max(get(g.Handles.rvvcurve,'ydata')); - set(g.Handles.rvvcurve,'xdata',t,'ydata',SET(no).RVV); - end - - newrvpeak=max(get(g.Handles.rvvcurve,'ydata')); - yborders=get(g.Handles.volumeaxes,'ylim'); - yroofpostcurves=yborders(2); - - if newvolpeak~=oldvolpeak || newrvpeak~=oldrvpeak || yroofprecurves~=yroofpostcurves || yborders(1)~=0 - %removeallbars - delete(g.Handles.timebarlv); - delete(g.Handles.volumeaxeshelpers); - delete(g.Handles.estext); - delete(g.Handles.edtext); - delete(g.Handles.esline); - delete(g.Handles.edline); - delete(g.Handles.lvmtext) - - g.Handles.timebarlv=[]; - g.Handles.volumeaxeshelpers = []; - g.Handles.estext=[]; - g.Handles.edtext=[]; - g.Handles.esline=[]; - g.Handles.edline=[]; - g.Handles.lvmtext=[]; - end - - %Texts and - %bars----------------------------------------------------------------------------- - - % here we do not want to mess with upper limit this should be set by - % the curves plotted so fixate the top limit - temp = get(g.Handles.volumeaxes,'ylim'); - - ylim(g.Handles.volumeaxes,'manual') - ylim(g.Handles.volumeaxes,[0 temp(2)]) - ttemp = [t;t]; - temp = [zeros(size(t)); repmat(0.1*(temp(2)-temp(1)),size(t))]; - - if length(g.Handles.volumeaxeshelpers)~=length(t) - delete(g.Handles.volumeaxeshelpers) - g.Handles.volumeaxeshelpers=[]; - end - - if isempty(g.Handles.volumeaxeshelpers) || any(~ishandle(g.Handles.volumeaxeshelpers)) - g.Handles.volumeaxeshelpers=plot(g.Handles.volumeaxes,ttemp,temp,'k-'); - %set(g.Handles.timebaraxes,'YTick',[]); - else -% if length(t)~=length(g.Handles.volumeaxeshelpers)%find(~isempty(g.Handles.volumeaxeshelpers))) -% delete(g.Handles.volumeaxeshelpers(length(t)+1:end)) -% end - instr=ones(1,length(t)); - xcell=mat2cell(ttemp,2,instr)'; - ycell=mat2cell(temp,2,instr)'; - set(g.Handles.volumeaxeshelpers,{'XData'},xcell,{'YData'},ycell) - end - - if isempty(g.Handles.timebarlv) || ~ishandle(g.Handles.timebarlv) - g.Handles.timebarlv = plot(g.Handles.volumeaxes,... - [t(SET(no).CurrentTimeFrame) t(SET(no).CurrentTimeFrame)],... - get(g.Handles.volumeaxes,'ylim'),'-','Color',lc); - set(g.Handles.timebarlv,'linewidth',2); - else - set(g.Handles.timebarlv,'xdata',[t(SET(no).CurrentTimeFrame) t(SET(no).CurrentTimeFrame)],'ydata',get(g.Handles.volumeaxes,'ylim'),'color',lc) - end - %plot(g.Handles.volumeaxes,ttemp,temp,'k-'); - - %ED and ES - temp = get(g.Handles.volumeaxes,'ylim'); - tempmax = temp(end); %JU - tempmin = temp(1); %JU - - if isempty(g.Handles.edtext) || ~ishandle(g.Handles.edtext) - g.Handles.edtext = text(... - 'position',[t(SET(no).EDT)-t(end)*0.05 tempmax-0.2*(tempmax-tempmin)],... - 'string','ED',... - 'parent',g.Handles.volumeaxes,... - 'color',lc,'FontWeight','bold'); - else - set(g.Handles.edtext,'position',[t(SET(no).EDT)-t(end)*0.05 tempmax-0.2*(tempmax-tempmin)],'color',lc); - end - - if isempty(g.Handles.edline) || ~ishandle(g.Handles.edline) - g.Handles.edline = plot(g.Handles.volumeaxes,... - [t(SET(no).EDT) t(SET(no).EDT)],[tempmax tempmax*0.8],'color',lc); - else - set(g.Handles.edline,'xdata',[t(SET(no).EDT) t(SET(no).EDT)],'ydata',[tempmax tempmax*0.8]) - end - - set([g.Handles.edtext g.Handles.edline],'ButtonDownFcn','segment(''esed_Buttondown'',''ed'')',... - 'color',lc,'linewidth',2); - set(g.Handles.volumeaxes,'ButtonDownFcn','segment(''volumeaxes_Buttondown'')'); - - - if isempty(g.Handles.estext) || ~ishandle(g.Handles.estext) - g.Handles.estext = text(... - 'parent',g.Handles.volumeaxes,... - 'position',[t(SET(no).EST)-0.05*t(end) tempmin+0.2*(tempmax-tempmin)],... - 'string','ES',... - 'color',lc,'FontWeight','bold'); - else - set(g.Handles.estext,'position',[t(SET(no).EST)-0.05*t(end) tempmin+0.2*(tempmax-tempmin)],'color',lc); - end - - if isempty(g.Handles.esline) || ~ishandle(g.Handles.esline) - g.Handles.esline = plot(g.Handles.volumeaxes,[t(SET(no).EST) t(SET(no).EST)],... - [tempmin tempmin+(0.2*(tempmax-tempmin))],'color',lc,'linewidth',2); - else - set(g.Handles.esline,'xdata',[t(SET(no).EST) t(SET(no).EST)],'ydata',[tempmin tempmin+(0.2*(tempmax-tempmin))],'color',lc) - end - - set([g.Handles.estext g.Handles.esline],'ButtonDownFcn','segment(''esed_Buttondown'',''es'')'); - maxlvm = max(SET(no).EPV-SET(no).LVV+SET(no).PV); - if ~isnan(maxlvm) - if ~isempty(g.Handles.lvmtext) - set(g.Handles.lvmtext,'position',[0.85*t(end) maxlvm+0.06*(tempmax-tempmin)]) - else - g.Handles.lvmtext = text(... - 'parent',g.Handles.volumeaxes,... - 'position',[0.85*t(end) maxlvm+0.06*(tempmax-tempmin)],... - 'string','LVM',... - 'color','blue','fontsize',8); - end - else - delete(g.Handles.lvmtext) - g.Handles.lvmtext=[]; - end -%------------------------------------------------------------------------------------------------------------ - - hold(g.Handles.volumeaxes,'off'); - set(g.Handles.timebarlv,'buttondownFcn','segment(''timebarlv_Buttondown'')'); - set(g.Handles.volumeaxes,'xlim',[t(1) t(end)]); %,'ticklength',[0 0]);%1000*60/SET(no).HeartRate]); - ylabel(g.Handles.volumeaxes,translation.dictionary('Volume [ml]'),'color',g.GUISettings.VolumeAxesColor); - xlabel(g.Handles.volumeaxes,translation.dictionary('Time [ms]'),'color',g.GUISettings.VolumeAxesColor); - set(g.Handles.volumeaxes,... - 'XColor',g.GUISettings.VolumeAxesColor,... - 'YColor',g.GUISettings.VolumeAxesColor); - set(g.Handles.volumeaxes, ... - 'Color',g.GUISettings.VolumeColorGraph); - end - - end - - - %------------------------- - function updateflowaxes(g) - %------------------------- - %Update the flow report axes in main GUI - global DATA SET - - no = DATA.FlowNO; - roinbr = DATA.FlowROI; - - if isempty(no) || SET(no).TSize<2 || isempty(SET(no).Flow) || isempty(SET(no).Flow.Result) || isempty(roinbr) || length(SET(no).Flow.Result)< roinbr || isempty(SET(no).Flow.Result(roinbr)) || isempty(SET(no).Flow.Result(roinbr).netflow) - cla(g.Handles.flowaxes); - g.Handles.timebarflow = []; - g.Handles.flowcurve = []; - set(g.Handles.flowaxes,'Visible','off'); - %set(g.Handles.flowuipanel,'Visible','off'); - %set(g.Handles.flowresultaxes,'Visible','off'); - else - lc = DATA.GUISettings.BarColor;%[55 119 106]/255; - - %set(g.Handles.flowuipanel,'Visible','on'); - set(g.Handles.flowaxes,'Visible','on'); - %set(g.Handles.flowresultaxes,'Visible','on'); - %Time resolved - t = SET(no).TimeVector*1000; - %flow curve - netflow = SET(no).Flow.Result(roinbr).netflow; - - %plot in color of roi - curvecolor=SET(no).Roi(roinbr).LineSpec(1); - - g.Handles.flowcurve = plot(g.Handles.flowaxes,t,netflow,[curvecolor,'.-']);%'b.-'); - hold(g.Handles.flowaxes,'on'); - set(g.Handles.flowcurve,'markersize',5); - % set y-lim dependent on netflow values - minflow = min(netflow); - maxflow = max(netflow); - set(g.Handles.flowaxes,'ylim',[floor((minflow-50)/100)*100 ceil((maxflow+50)/100)*100]); - %plot line at zero - plot(g.Handles.flowaxes,[t(1) t(end)],[0 0],'k:'); - %outer time bars - plot(g.Handles.flowaxes,[t(1) t(1)],get(g.Handles.flowaxes,'ylim'),'color',lc)%'g-'); - plot(g.Handles.flowaxes,[t(end) t(end)],get(g.Handles.flowaxes,'ylim'),'color',lc)%'g-'); - %current time - g.Handles.timebarflow = plot(g.Handles.flowaxes,... - [t(SET(no).CurrentTimeFrame) t(SET(no).CurrentTimeFrame)],... - get(g.Handles.flowaxes,'ylim'),'-','Color',lc); - temp = get(g.Handles.flowaxes,'ylim'); - ttemp = [t;t]; - temp = [repmat(temp(1),size(t));repmat(temp(1)+0.1*(temp(2)-temp(1)),size(t))]; - plot(g.Handles.flowaxes,ttemp,temp,'k-'); - set(g.Handles.timebarflow,'linewidth',2); - set(g.Handles.timebarflow,'buttondownFcn','segment(''timebarflow_Buttondown'')'); - set(g.Handles.flowaxes,'xlim',[t(1) t(end)]); %,'ticklength',[0 0]);%1000*60/SET(no).HeartRate]); - hold(g.Handles.flowaxes,'off'); - set(g.Handles.flowaxes,'ButtonDownFcn','segment(''flowaxes_Buttondown'')'); - %labels and color - ylabel(g.Handles.flowaxes,translation.dictionary('Flow [ml/s]'),'color',g.GUISettings.VolumeAxesColor); - xlabel(g.Handles.flowaxes,translation.dictionary('Time [ms]'),'color',g.GUISettings.VolumeAxesColor); - set(g.Handles.flowaxes,... - 'XColor',g.GUISettings.VolumeAxesColor,... - 'YColor',g.GUISettings.VolumeAxesColor); - set(g.Handles.flowaxes, ... - 'Color',g.GUISettings.VolumeColorGraph); - if ~isempty(SET(SET(no).Flow.PhaseNo).Flow.PhaseCorr) - if ~isfield(SET(SET(no).Flow.PhaseNo).Flow,'PhaseCorrTimeResolved') - mywarning('Incompatible eddy current correction. Correction reset.',DATA.GUI.Segment); - else - g.Handles.flowtext = text(get(g.Handles.flowaxes,'XLim'),get(g.Handles.flowaxes,'YLim'),'[Eddy]', ... - 'Parent',g.Handles.flowaxes,'FontSize',10,'HorizontalAlignment','right','VerticalAlignment','top'); - end - else -% g.Handles.flowtext = text(get(g.Handles.flowaxes,'XLim'),get(g.Handles.flowaxes,'YLim'),'hej', ... -% 'Parent',g.Handles.flowaxes,'FontSize',11,'HorizontalAlignment','right','VerticalAlignment','top'); - end - end - end - - %-------------------------------------- - function measurefontsize(g,panel,index) - %-------------------------------------- - %Sets measure font size. Used in CVQgui. - end - - %------------------------------------------------------------------ - function addmainicon_helper(g,callback,tooltip,cdata,tag,separator) - %------------------------------------------------------------------ - %Helper function to add an icon - - if nargin<5 - myfailed('Too few input arguments.',g.GUI.Segment); - return; - end; - - if nargin<6 - separator = 'off'; - end; - - props = []; - props.ClickedCallback = callback; - props.ToolTip = translation.dictionary(tooltip); - props.Tag = tag; - props.CData = cdata; - props.Separator = separator; - g.Handles.(tag) = uitoggletool(g.Handles.maintoolbar,props); - - end - - %-------------------------------------- - function heartratezero(g, heartrateest) - %-------------------------------------- - %React upon a heart rate read as zero from DICOM in openfile('initset') - mywarning(dprintf(... - 'Specified Heart Rate is 0, assuming alive patient, guess on %0.5g (based on timeincrement)',... - heartrateest),g.GUI.Segment); - end - - %---------------------------------- - function drawsectorgrid(g,no,panel) - %---------------------------------- - %Overloaded in RVQ GUI - end - - %---------------------------- - function buttonup_Callback(g) - %---------------------------- - %General buttonupfunction. Overloaded in RVQ GUI - - set(g.imagefig,'WindowButtonMotionFcn','segment(''toggleplaceholdermotion'')'); - %drawfunctions('drawsliceno'); - end - - %----------------------------------------- - function printthumbnailnumber(g,thumbsize) - %----------------------------------------- - %Overloaded in RVQ GUI - global SET - fontsize = thumbsize/23; - - g.Handles.datasetnumber = []; - - numletters=8;%thumbsize/fontsize; - for loop=1:length(SET) - dosplit=0; - margin = fontsize; - str = SET(loop).ImageType; - if ~isempty(str) - str = strtrim(str); - end; - listmap={'Feature tracking','FT';... - 'Late enhancement','LGE';... - 'Perfusion rest', 'Perf R';... - 'Perfusion rest aligned', 'Perf R a';... - 'Perfusion stress', 'Perf S';... - 'Perfusion stress aligned', 'Perf S a.';... - 'Strain from tagging','Tagging';... - 'T1 map pre','T1 Pre';... - 'T1 map post', 'T1 Post';... - 'T2 map pre','T2 Pre';... - 'T2 map post', 'T2 Post';... - 'T2star', 'T2*';... - 'Flow (magnitude)','Flow';... - 'Flow (through plane)','Flow';... - 'Inspiration','Insp';... - 'Expiration','Exp'}; - - for i = 1:size(listmap,1) - if strcmpi(listmap{i,1},str) - str=listmap{i,2}; - end - end - - imvpmap={'Short-axis', 'SAX';... - 'Short-axis basal', 'SAX basal';... - 'Short-axis', 'SAX mid';... - 'Short-axis', 'SAX apical';... - 'Sagittal','Sag';... - 'Coronal','Cor';... - 'Frontal','Front';... - 'Transversal', 'Trans' - '2CH','2CH';... - '3CH','3CH';... - '4CH','4CH'}; - - addimvp=0; - if isempty(SET(loop).ImageViewPlane) - SET(loop).ImageViewPlane = ''; - end; - strimvp = SET(loop).ImageViewPlane; - if ~isempty(strimvp) - strimvp = strtrim(strimvp); - end; - for i = 1:size(imvpmap,1) - if strcmpi(imvpmap{i,1},strimvp) - strimvp=imvpmap{i,2}; - addimvp=1; - end - end - - if addimvp - str=[str,', ',strimvp]; - end - - if length(str)>10 - str=str(1:8); - end - -% if length(str)>numletters -% %group into cell of strings -% %check for spaces close to 10 line -% formatstring='%d. %s'; -% strcell={}; -% str_tmp=str; -% numbreaks=0; -% -% while true -% if numbreaks>0 -% numletters=12; -% end -% -% ind = find(isspace(strtrim(str_tmp))); -% tmp=ind(find((ind>floor(1/2*numletters)).*(ind - end - end - - if ~isempty(pathname) && exist(pathname,'dir') - return - end - - if ispc - %Is Windows, check for better - temp = getenv('APPDATA'); - if not(isempty(temp)) - pathname = temp; - else - temp = getenv('USERPROFILE'); - if not(isempty(temp)) - pathname = temp; - else - temp = getenv('HOMEPATH'); - if not(isempty(temp)) - pathname = temp; - end; - end; - end; - - %Check if subdirectory exists - if not(exist([temp filesep foldername],'dir')) - temppath = pwd; - cd(pathname); - disp(dprintf('Creating new folder %s%s%s',temp,filesep,foldername)); - suc = mkdir(foldername); - cd(temppath); - if not(suc) - myfailed(dprintf('Could not create %s%s%s',temp,filesep,foldername)); - end; - end; - - %Add Segment to the path - pathname= [pathname filesep foldername]; - else - pathname = pwd; - end; %is pc - end - - %----------------------- - function standardpref(g) - %----------------------- - %Setup language. Overloaded in GUI's where translation is available. - %Can also be used to set other preferences that are not optional. - g.Pref.Language = 'English'; %Override language selection from other GUI - end - - - %---------------------------- - function updatepacslabels(g) - %---------------------------- - %Change to name of PACS in labels if only one PACS connection exists. - %Overloaded in Segment CMR GUI. - end - - %------------------------------ - function updatesax3display(g,~) - %------------------------------ - %Update data used to correctly display segmentation in SAX3 view. - %Overloaded in Segment SPECT GUI - end - - %------------------------ - function setglobalstacks(g) - %------------------------ - %Find the best stacks for report LV, RV and Flow in main result - - global DATA - - cinestacks = findfunctions('findcineshortaxisno',true); - if ~isempty(cinestacks) - DATA.LVNO = cinestacks(1); - DATA.RVNO = cinestacks(2); - else - DATA.LVNO = []; - DATA.RVNO = []; - end - [DATA.FlowNO, DATA.FlowROI] = findfunctions('findflowaxisno'); - end - - - %----------------------- - function initbullseyeslices(g) %#ok - %----------------------- - %Overloaded in Segment CMR GUI, Segment CT GUI and Segment Spect GUI - end - - %----------------------- - function initbullseyes(g) %#ok - %----------------------- - %Overloaded in Segment CT GUI - end - - %-------------------------- - function r = isorthoview(g) - %-------------------------- - %Check if we have a proper setup for orthoview - r = numel(g.ViewPanels) >= 3 && ... - all(g.ViewPanels(1:3) == g.ViewPanels(1)); - end - -% %------------------------------- -% function keyreleased(g) -% %------------------------------- -% g.GUI.needrest = 1; -% end - %---------------------- - function synchronize(g) - %----------------------- - %toggle synchronize option currently makes - %slice toggling - %time toggling - %go to ed - %go to es - %execute for all stacks. - - stateandicon = segment('iconson','synchronize'); - g.Synchronize=stateandicon{1}; - end - %--------------------------------- - function keypressed(g,fignum,evnt) - %--------------------------------- - %Called when key is pressed. Overloaded in Segment CT GUI. - global SET NO DATA - persistent starttime; - tol=0.2; - d = datevec(now); - tnow = d(6); - diff=tnow-starttime; - if ~isempty(diff) && difflength(g.ViewPanels) - temp = 1; - end; - g.CurrentPanel = temp; - - if g.ViewPanels(temp)~=0 - %valid - segment_main('switchtopanel',temp); - g.CurrentPanel = temp; - return; - end; - end; - segment_main('switchtopanel',g.CurrentPanel) - else - %Toggle the gui - %Given an update tool string toggle icons 2 the given tool -% if strcmp(g.CurrentTool(1:4),'draw'); -% g.CurrentTool(1:4)=[]; -% g.CurrentTool=[g.CurrentTool,'pen']; -% end -% -% do buttonup before in case it didn't manage. - %set(DATA.imagefig,'WindowButtonMotionFcn','') -% buttonupfcn = get(DATA.imagefig,'WindowButtonUpFcn'); -% set(DATA.imagefig,'WindowButtonUpFcn','') -% run(buttonupfcn); -% -% % this is safe since a buttonup will be toggled to! -% set(DATA.imagefig,'WindowButtonDownFcn','') -% -% set(DATA.imagefig,'WindowButtonMotionFcn','') -% set(DATA.imagefig,'WindowButtonUpFcn','') - oldtool=g.CurrentTool; - g.CurrentTool=toolstruct.(g.CurrentTool); - g.guitoggletool(g.CurrentTool,oldtool); -% donotchangetfo = true; -% updatetool(toolstruct.(g.CurrentTool), [], donotchangetfo); - end - -% case 'shift-l' -% % g.updateicons('lv'); %themes: L(LV),R(RV),V(Scar/Viability),F(ROI/Flow), M(MaR), I(Misc), E(perfusion), T(T2*) -% case 'shift-r' -% %g.updateicons('rv'); %themes: L,R,V,F -% case 'shift-f' -% %g.updateicons('roi'); %themes: L(LV),R(RV),V(Scar/Viability),F(ROI/Flow), M(MaR), I(Misc) -% case 'shift-v' -% %g.updateicons('scar'); %themes: L,R,V,F -% case 'shift-m' -% %g.updateicons('mar'); %themes: L(LV),R(RV),V(Scar/Viability),F(ROI/Flow), M(MaR), I(Misc), E(perfusion), T(T2*) -% case 'shift-i' -% %g.updateicons('misc'); %themes: L(LV),R(RV),V(Scar/Viability),F(ROI/Flow), M(MaR), I(Misc) -% case 'shift-e' -% return; %reserved for theme Perfusion -% case 'shift-t' -% return;% reserved for g.updateicons('t2'); %themes: L(LV),R(RV),V(Scar/Viability),F(ROI/Flow), M(MaR), I(Misc), E(perfusion), T(T2*) -% case 'shift-n' %Select LV Endo pen -% %g.updateicons('lv'); -% updatetool('drawendo'); -% case 'shift-b' %Select LV Epi pen -% %g.updateicons('lv'); -% updatetool('drawepi'); -% case 'shift-g' %select LV Endo interp -% %g.updateicons('lv'); -% updatetool('interpendo'); -% case 'shift-h' %Select LV Epi interp -% %g.updateicons('lv'); -% updatetool('interpepi'); -% - - case 'e' - %compress imagemapping - - %Miscellaneous commands - case 'q' - fcn = get(g.Handles.imagehandle,'ButtonDownFcn'); - set(g.imagefig,'SelectionType','normal') - eval(fcn); - fcn = get(g.imagefig,'WindowButtonUpFcn'); - pause(0.3); - eval(fcn); - case 'w' - if ~isempty(g.GUI.T2Star) - %Call t2star centerpoint move funtion: - fcn = 't2star.t2star(''point_up'')'; - eval(fcn); - else - fcn = get(g.Handles.imagehandle,'ButtonDownFcn'); - set(g.imagefig,'SelectionType','alt') - eval(fcn); - end - case 'ctrl-b' - reportbullseye; - case 'ctrl-n' - filemenu('loadnext_Callback'); - % case 'ctrl-o' open file loader set in GUI to be able to overload callback depending on gui - case 'ctrl-p' - patientdatabase; - case 'shift-ctrl-w' - g.filecloseall_Callback; - % case 'ctrl-q' quit program set in GUI to be able to overload callback depending on gui - case 'ctrl-z' - tools('undosegmentation_Callback'); - % Set in GUIDE, so they are disabled, but leave here for documentation! - case 'ctrl-0' - segment_main('viewzoomin_Callback'); - case 'ctrl-hyphen' - segment_main('viewzoomout_Callback'); - case 'shift-ctrl-b' - segmenthelp('supportreq_Callback'); %Open supportreq GUI - case 'ctrl-c' - return; - case 'shift-ctrl-e' - segment_main('evalcommand_Callback'); - case 'ctrl-t' %plot flow - reportflow(); - - case 'k' % TEMPORARY HOTKEY, MAY BE CHANGED - plugin_3dflow('calckineticenergy_Callback'); - case 'shift-k' % TEMPORARY HOTKEY, MAY BE CHANGED - plugin_3dflow('createvelocityset_Callback'); - case 'shift-ctrl-k' % TEMPORARY HOTKEY, MAY BE CHANGED - reportflow3d2d(NO); - case 'y' %TEMPORARY - v = get(g.Handles.imageaxes(g.CurrentPanel),'view'); - set(g.Handles.imageaxes(g.CurrentPanel),'view',[v(1)+1 90]); - case 'shift-y' %TEMPORARY - v = get(g.Handles.imageaxes(g.CurrentPanel),'view'); - set(g.Handles.imageaxes(g.CurrentPanel),'view',[v(1)-1 90]); - case 'shift-ctrl-t' %TEMPORARY - t2star.t2starnew('calc'); - case 'ctrl-alt-t' - g.maketest; - case 'ctrl-alt-a' - %Fully Automatic Vessel Segmentation in 2D PC-MRI: - vesselsnake_overview('segmentaorta') - case 'ctrl-alt-v' - %New method for semi-Automatic Vessel Segmentation in 2D PC-MRI: - oldpref=DATA.ThisFrameOnly; - vesselsnake_flowtrackroi('flowtrackroi'); - DATA.ThisFrameOnly=oldpref; - case 'ctrl-alt-space' - %Import T1map: - cxt1map2segment() - case 'ctrl-alt-z' - spect.spectautobutton() -% case 'tab' -% ind=DATA.Handles.toggleiconholder.findindented; -% indnext=ind+1; -% iconcell = DATA.Handles.toggleiconholder.iconCell; -% if indnext>DATA.Handles.toggleiconholder.numberoficons; -% indnext=1; -% end -% iconcell{ind}.cdataDisplay=iconcell{ind}.cdata; -% iconcell{ind}.isindented=0; -% iconcell{indnext}.cdataDisplay=iconcell{indnext}.cdataIndent; -% iconcell{indnext}.isindented=1; -% % switch indnext -% % case 1 -% % g.togglebuttonLV_Callback -% % case 2 -% % g.togglebuttonRV_Callback -% % case 3 -% % g.togglebuttonROIFLOW_Callback -% % case 4 -% % g.togglebuttonVia_Callback -% % case 5 -% % g.togglebuttonAnalysis_Callback -% % case 6 -% % g.togglebuttonImage_Callback -% % end -% % run(iconcell{ind}.execute); -% feval(iconcell{indnext}.execute); -% g.Handles.toggleiconholder.render; -% % g.Handles.configiconholder.render; - - %Set keypress functions - %set(DATA.imagefig,'keypressfcn',@(fignum,evnt)segment('keypressed',fignum,evnt)); - %updatetool(g.CurrentTool) -% gcf(DATA.fig) - end; - end - - %------------------------------------------------ - function guitoggletool(varargin) - %------------------------------------------------ - %Defines which tool to toggle to for certain coupled tools - g=varargin{1}; - tool2toggle2=varargin{2}; - oldtool=varargin{3}; - %Given an update tool string toggle icons 2 the given tool - if strcmp(tool2toggle2(1:4),'draw'); - tool2toggle2(1:4)=[]; - tool2toggle2=[tool2toggle2,'pen']; - end - - if strcmp(oldtool(1:4),'draw'); - oldtool(1:4)=[]; - oldtool=[oldtool,'pen']; - end - - g.Handles.configiconholder.indent(tool2toggle2,1) - -% icons={g.Icons.lviconcell;g.Icons.rviconcell;g.Icons.roiflowiconcell;g.Icons.viabilityiconcell;... -% g.Icons.analysisiconcell; g.Icons.imageiconcell}; -% n=length(icons); -% for k=1:n; -% iconcell=icons{k}; -% N=length(iconcell); -% %return icon state -% for i=1:N -% if strcmp(iconcell{i}.name,tool2toggle2) -% holderind=k; -% iconind=i; -% end -% %if strcmp(iconcell{i}.name,oldtool) -% % oldholderind=k; -% %end -% end -% end -% icon2indent=[]; -% icon2undent=[]; -% iconcell=g.Handles.configiconholder.iconCell; -% N=length(iconcell); -% for i=1:N -% if strcmp(iconcell{i}.name,tool2toggle2) -% icon2indent=iconcell{i}; -% end -% if strcmp(iconcell{i}.name,oldtool) -% icon2undent=iconcell{i}; -% end -% end - - % if holderind==oldholderind - %undent current tool this is safe since tools always are toggle - %buttons. - %stateandicon=segment('iconson',oldtool); - %stateandicon{2}.isindented=0; - %stateandicon{2}.cdataDisplay=stateandicon{2}.cdata; - %end - - %g.Handles.toggleiconholder.clickedicon=icon2indent;%g.Handles.toggleiconholder.iconCell{holderind}; - %we want to go to the toggle menu with the tool2toggle2 - -% -% if ~isempty(icon2indent) -% icon2indent.cdataDisplay=icon2indent.cdataIndent;%icons{holderind}{iconind}.cdataIndent; -% icon2indent.isindented=1; -% end -% g.Handles.configiconholder.clickedicon=icon2indent;%{holderind}{iconind}; -% if ~isempty(icon2undent) -% icon2undent.isindented=0; -% icon2undent.cdataDisplay=icon2undent.cdata; -% end -% g.Handles.configiconholder.render; - end - - %------------------------------------------------------ - function [measure,slice] = getmeasurecoords(g,no,panel) - %------------------------------------------------------ - %Get coordinates of measurements with respect to the current view - global SET - - switch g.ViewPanelsType{panel} - case 'hla' - measure = struct( ... - 'X',{SET(no).Measure.Z}, ... - 'Y',{SET(no).Measure.Y}, ... - 'Z',{SET(no).Measure.X}); - slice = SET(no).HLA.slice; - case 'vla' - measure = struct( ... - 'X',{SET(no).Measure.Z}, ... - 'Y',{SET(no).Measure.X}, ... - 'Z',{SET(no).Measure.Y}); - slice = SET(no).VLA.slice; - case 'gla' - ang = SET(no).GLA.angle; - res = SET(no).ResolutionY*cos(ang)+SET(no).ResolutionX*abs(sin(ang)); - measure = struct( ... - 'X',{SET(no).Measure.Z}, ... - 'Y',cellfun(@(y,x)1/res*(SET(no).ResolutionY*(y-SET(no).GLA.y0)*cos(ang) + ... - SET(no).ResolutionX*(x-SET(no).GLA.x0)*sin(ang)), ... - {SET(no).Measure.Y},{SET(no).Measure.X},'UniformOutput',false), ... - 'Z',cellfun(@(y,x)1/res*(SET(no).ResolutionY*(y-SET(no).GLA.y0)*-sin(ang) + ... - SET(no).ResolutionX*(x-SET(no).GLA.x0)*cos(ang)), ... - {SET(no).Measure.Y},{SET(no).Measure.X},'UniformOutput',false)); - slice = 0; - otherwise - measure = struct( ... - 'X',{SET(no).Measure.X}, ... - 'Y',{SET(no).Measure.Y}, ... - 'Z',{SET(no).Measure.Z}); - slice = SET(no).CurrentSlice; - end - end - - end - - methods(Access='protected') - - %--------------------------------------- - function switchtoimagestack_part2(g, no) - %--------------------------------------- - %switchtoimagestack continued. Overloaded in SegmentGUI and CVQgui - global SET NO - - %Loop until there are no blocking windows left - while ~isempty(g.BlockingFigs) - - %Check deleted windows - ind = true(1,length(g.BlockingFigs)); - for loop=1:length(ind) - try - get(g.BlockingFigs); - catch %#ok - ind(loop) = false; - end; - end; - - %Remove deleted windows - g.BlockingFigs = g.BlockingFigs(ind); - - if ~isempty(g.BlockingFigs) - uiwait(msgbox('Close all reviewing windows, then press OK before changing current image stack.')); - end; - end; - - %if switchtostack is not in view, update current panel - if ~ismember(no,g.ViewPanels) - emptypanel = find(g.ViewPanels==0,1); - if isempty(emptypanel) - emptypanel = numel(g.ViewPanels); - end - g.ViewPanels(emptypanel) = no; - g.ViewPanelsType{emptypanel} = 'one'; - g.ViewIM{emptypanel} = []; - drawfunctions('drawimagepanel',emptypanel); - segment('switchtopanel',emptypanel,false); %Do not update imagestack - end - - %Store it - NO = no; - - %Double check out of range - if NO>length(SET) - NO = length(SET); - end; - - if NO<1 - NO = 1; - end; - - %Variables that has to be reset in the change are: - % endoedgedetect, epiedgedetect, endoedge, epiedge - % BpInt, MInt, BALLOON, Montage, Wallthickness, Radius, - % MaxRadialVel, BalloonLevel, run - % interactionlock, LevelSet - - %Update viability menu if no scar is present then - %options are hidden. -% viability('viabilitymenu'); - if isempty(SET(NO).Scar) && strcmp(g.CurrentTheme,'scar') - %g.updateicons('lv'); - end - - g.Run = 0; - g.cleardatalevelset; - - g.EndoEdgeDetected = false; - g.EpiEdgeDetected = false; - g.EndoEDGE0 = []; - g.EndoEDGE1 = []; - g.EndoEDGE2 = []; - g.EndoEDGE3 = []; - g.EpiEDGE0 = []; - g.EpiEDGE1 = []; - g.EpiEDGE2 = []; - g.EpiEDGE3 = []; - g.BpInt = -1; - g.MInt = [-1,-1]; - g.TInt = -1; - g.BalloonLevel = -1; - g.BALLOON = []; - g.EndoBalloonForce = []; - g.EpiBalloonForce = []; - - %Update that makes the function much slower, seems unnecessary -% drawfunctions('drawimageno',NO); -% -% %Switch to a panel in that stack, if possible -% if force -% ind=find(g.ViewPanels==NO); -% if not(isempty(ind)) -% g.CurrentPanel=ind(1); -% end -% end - % end update - - drawfunctions('drawthumbnailframes'); - - if ~isempty(g.Handles.imageaxes) && all(ishandle(g.Handles.imageaxes)) - %Make now one orange - set(g.Handles.imageaxes,... - 'xcolor',[0 0 0],'ycolor',[0 0 0]); - set(g.Handles.imageaxes(g.CurrentPanel),... - 'xcolor',g.GUISettings.AxesColor,'ycolor',g.GUISettings.AxesColor,... - 'linewidth',2.5); - end - - %Enable/Disable play icon etc - %g.updatetimethings; - %g.updateaxestables; -% %Update volumeaxes - g.updateaxestables('allreports'); -% segment('updatevolume'); -% segment('updateflow'); - - %Update title on window - g.updatetitle; - end - - end - - methods(Static) - - %-------------------- - function versionhello - %-------------------- - %Versionhello, overloaded in CVQgui, RVQ, SegmentTransfer, Segment CMR - %(soon) - - getmodule('versionhello'); - if verLessThan('matlab','8.3') - mywarning(['Segment was developed using MATLAB 8.3 (R2014a). '... - 'You are now running on an older version, which may cause errors.']); - end - end - - %--------------------- - function orthoview(no) - %--------------------- - % Create orthogonal view for stack no - global SET NO - if nargin < 1 - no = NO; - end - - SET(no).HLA.slice = round(SET(no).XSize/2); - SET(no).HLA.maxslice = SET(no).XSize; - SET(no).HLA.ZoomState = []; - - SET(no).VLA.slice = round(SET(no).YSize/2); - SET(no).VLA.maxslice = SET(no).YSize; - SET(no).VLA.ZoomState = []; - - ang = 2*pi/8; - SET(no).GLA.angle = ang; - SET(no).GLA.slice = 0; - SET(no).GLA.ZoomState = []; - - updatetool('orthoview'); - %mywaitbarstart(); - drawfunctions('drawimageview',[no no no no],[2 2],{'ortho','hla','vla','gla'}); - %mywaitbarclose(); - %pause(0.1); - %updatetool('orthoview'); - end - - %--------------------- - function startlog(log) - %--------------------- - %Start Segment log. - diary(log); - end - - %--------------------- - function stoplog - %--------------------- - %Stop Segment logging. - diary off; - end - - %----------------------------- - function setsectorrotation(no) - %----------------------------- - %Overloaded in RVQ GUI - end - - %--------------------------------------- - function filename = generatesavefilename - %--------------------------------------- - %Called by segment('filesaveallas_Callback'). Overloaded in CVQgui. - global SET - filename = [removeforbiddenchars([SET(1).PatientInfo.Name '-' datestr(now,'yyyy-mm-dd')]) '.mat']; - end - - %----------------------------------- - function ok = manualdraw_Buttonup_roi(no,xr,yr,slice) - %----------------------------------- - %Draw new ROI. Called by segment_main('manualdraw_Buttonup') - %Overloaded in CVQgui and RVQgui. - - global SET DATA - - ok = true; - if any(SET(no).RoiCurrent>SET(no).RoiN | SET(no).RoiCurrent<1) - SET(no).RoiCurrent = SET(no).RoiN; - end; - if isempty(SET(no).RoiCurrent) - SET(no).RoiCurrent = SET(no).RoiN; - end; - - SET(no).RoiN = SET(no).RoiN+1; - - SET(no).Roi(SET(no).RoiN).X = repmat(yr',[1 SET(no).TSize]); - SET(no).Roi(SET(no).RoiN).Y = repmat(xr',[1 SET(no).TSize]); - SET(no).Roi(SET(no).RoiN).T = 1:SET(no).TSize; - SET(no).Roi(SET(no).RoiN).Z = slice; - SET(no).Roi(SET(no).RoiN).Sign = 1; - if SET(no).RoiN==1 - SET(no).Roi(SET(no).RoiN).Name = sprintf('ROI-%d',SET(no).RoiN); - SET(no).Roi(SET(no).RoiN).LineSpec = 'b-'; - else - if length(SET(no).Roi(SET(no).RoiCurrent(end)).Name)>=4 && isequal(SET(no).Roi(SET(no).RoiCurrent(end)).Name(1:4),'ROI-') - SET(no).Roi(SET(no).RoiN).Name = sprintf('ROI-%d',SET(no).RoiN); - else - SET(no).Roi(SET(no).RoiN).Name =SET(no).Roi(SET(no).RoiCurrent(end)).Name; - end - SET(no).Roi(SET(no).RoiN).LineSpec = SET(no).Roi(SET(no).RoiCurrent(end)).LineSpec; - end; - roi('roiforceapply'); - - %Calculate area and intensity of ROI - [~,SET(no).Roi(SET(no).RoiN).Area] = ... - calcfunctions('calcroiarea',no,SET(no).RoiN); - [m,sd]=calcfunctions('calcroiintensity',no,SET(no).RoiN); - SET(no).Roi(SET(no).RoiN).Mean = m; - SET(no).Roi(SET(no).RoiN).StD = sd; - - SET(no).RoiCurrent = SET(no).RoiN; - - %update flow result panel - if ~isempty(DATA.FlowNO) && ismember(DATA.FlowNO,SET(no).Linked) && ~isempty(DATA.FlowROI) - if SET(no).RoiN <1 - DATA.FlowROI = []; - else - calcfunctions('calcflow',no); - end - end - DATA.updateaxestables('area',no); - - end - %------------------------------------- - function setribbonimages(language) - %------------------------------- - %This function is used for translation and needs to be updated when - %adding ribbons. - global DATA - g=DATA; - - - if strcmp(language,'English') - if strcmp(g.ProgramName,'Segment CMR') - g.Handles.toggleiconholder.iconCell{3}.cdata=g.Icons.toggleicons.ribbonflowoff; - g.Handles.toggleiconholder.iconCell{3}.cdataIndent=g.Icons.toggleicons.ribbonflowon; - g.Handles.toggleiconholder.iconCell{4}.cdata=g.Icons.toggleicons.ribbonviabilityoff; - g.Handles.toggleiconholder.iconCell{4}.cdataIndent=g.Icons.toggleicons.ribbonviabilityon; - g.Handles.toggleiconholder.iconCell{6}.cdata=g.Icons.toggleicons.ribbonanalysisoff; - g.Handles.toggleiconholder.iconCell{6}.cdataIndent=g.Icons.toggleicons.ribbonanalysison; - g.Handles.toggleiconholder.iconCell{7}.cdata=g.Icons.toggleicons.ribbonimageoff; - g.Handles.toggleiconholder.iconCell{7}.cdataIndent=g.Icons.toggleicons.ribbonimageon; - else - g.Handles.toggleiconholder.iconCell{4}.cdata=g.Icons.toggleicons.ribbonanalysisoff; - g.Handles.toggleiconholder.iconCell{4}.cdataIndent=g.Icons.toggleicons.ribbonanalysison; - g.Handles.toggleiconholder.iconCell{5}.cdata=g.Icons.toggleicons.ribbonimageoff; - g.Handles.toggleiconholder.iconCell{5}.cdataIndent=g.Icons.toggleicons.ribbonimageon; - end - - - else - if strcmp(g.ProgramName,'Segment CMR') - g.Handles.toggleiconholder.iconCell{3}.cdataIndent=g.Icons.toggleicons.(['ribbonflowon_',language]); - g.Handles.toggleiconholder.iconCell{3}.cdata=g.Icons.toggleicons.(['ribbonflowoff_',language]); - g.Handles.toggleiconholder.iconCell{4}.cdata=g.Icons.toggleicons.(['ribbonviabilityoff_',language]); - g.Handles.toggleiconholder.iconCell{4}.cdataIndent=g.Icons.toggleicons.(['ribbonviabilityon_',language]); - g.Handles.toggleiconholder.iconCell{6}.cdata=g.Icons.toggleicons.(['ribbonanalysisoff_',language]); - g.Handles.toggleiconholder.iconCell{6}.cdataIndent=g.Icons.toggleicons.(['ribbonanalysison_',language]); - g.Handles.toggleiconholder.iconCell{7}.cdata=g.Icons.toggleicons.(['ribbonimageoff_',language]); - g.Handles.toggleiconholder.iconCell{7}.cdataIndent=g.Icons.toggleicons.(['ribbonimageon_',language]); - else - g.Handles.toggleiconholder.iconCell{4}.cdata=g.Icons.toggleicons.(['ribbonanalysisoff_',language]); - g.Handles.toggleiconholder.iconCell{4}.cdataIndent=g.Icons.toggleicons.(['ribbonanalysison_',language]); - g.Handles.toggleiconholder.iconCell{5}.cdata=g.Icons.toggleicons.(['ribbonimageoff_',language]); - g.Handles.toggleiconholder.iconCell{5}.cdataIndent=g.Icons.toggleicons.(['ribbonimageon_',language]); - end - end - - for i = 1:length(g.Handles.toggleiconholder.iconCell) - cdataIndent=g.Handles.toggleiconholder.iconCell{i}.cdataIndent; - cdata=g.Handles.toggleiconholder.iconCell{i}.cdata; - g.Handles.toggleiconholder.iconCell{i}.generateclickeddisabledandindent(cdata,cdataIndent); - if ~g.Handles.toggleiconholder.iconCell{i}.enabled - g.Handles.toggleiconholder.iconCell{i}.cdataDisplay=g.Handles.toggleiconholder.iconCell{i}.cdataDisabled; - elseif g.Handles.toggleiconholder.iconCell{i}.isindented - g.Handles.toggleiconholder.iconCell{i}.cdataDisplay=g.Handles.toggleiconholder.iconCell{i}.cdataIndent; - else - g.Handles.toggleiconholder.iconCell{i}.cdataDisplay=g.Handles.toggleiconholder.iconCell{i}.cdata; - end - - end - g.Handles.toggleiconholder.render; - end - %---------------------------------------------------------- - function handle = iconcdatahelper(handle,icondata,tiptext) - %---------------------------------------------------------- - %Helper function to updateicons - if nargin==2 - set(handle,'cdata',icondata); - else - set(handle,'cdata',icondata,'Tooltipstring',translation.dictionary(tiptext)); - end; - end - - %------------------------------------------- - function iconcallbackhelper(handle,callback) - %------------------------------------------- - %Helper function to updateicons. - set(handle,'callback',sprintf('updatetool(''%s'')',callback)); - end - - %--------------------------------------- - function pointshowthisframeonly_Callback - %--------------------------------------- - %Callback to make the current point visible in this time frame only. - %Overloaded in CVQgui. - global SET NO - - %Use to point to mag data set - no = NO; - if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; - end; - - % CVQ has this enabled by default for all points, therefore this - % leads to duplicates in the undo history. - tools('enableundo',no); - - pos = annotationpoint('pointfind'); - if isnan(pos) - myfailed('No point found.'); - return; - end - SET(no).Point.T(pos) = SET(no).CurrentTimeFrame; - drawfunctions('drawimageno'); - end - - %------------------ - function updateedes - %------------------ - %Overloaded in CVQgui - end - - %------------------------------- - function initreportflow(handles) %#ok - %------------------------------- - %Overloaded in CVQgui. - end - - %-------------------------- - function c = centercrossdef - %-------------------------- - %Define color of image center cross - c = [1 1 1]; - end - - %----------------------------------------------------------- - function h = mywaitbarstart(iter,stri,ignorelimit,fighandle) - %----------------------------------------------------------- - %Makes it possible to overload the mywaitbarstart behaviour - if nargin<2 - myfailed('Expected two or more input arguments.'); - return; - end; - - stri = translation.dictionary(stri); - - myworkon; - - if length(iter)>1 - iter = length(iter); - end; - - h = []; - h.iter = iter; - h.count = 0; - h.oldfrac = 0; - - if nargin>2 - h.ignorelimit = ignorelimit; - else - h.ignorelimit = 1; - end; - - %Check if empty vector supplied. - if isempty(h.ignorelimit) - h.ignorelimit = 1; %default - end; - - if h.iter>h.ignorelimit - h.h = waitbar(0,stri); - %set(h.h,'visible','off'); - else - h.h = []; - end; - - %This code does not work with Matlab R2010, there waitbar is not a - %handle, it is a class. -% try -% if nargin<4 -% myadjust(h.h); %Adjust horisontally! -% else -% myadjust(h.h,fighandle); %Adjust horisontally! -% end; -% catch %#ok -% end - - %set(h.h,'visible','on'); - flushlog; - end - - %------------------------- - function mywaitbarclose(h) - %------------------------ - %Makes it possible to overload mywaitbar behaviour - - if isempty(h.h) - else - close(h.h); - end; - - flushlog; - myworkoff; - end; - - %-------------------------- - function h = mywaitbarupdate(h,stri) - %-------------------------- - %Makes it possible to overload mywaitbar behaviour - h.count = h.count+1; - if isempty(h.h) - return; - end; - newfrac = round(20*h.count/h.iter); - if newfrac==h.oldfrac - else - h.oldfrac = newfrac; - if nargin > 1 && ~isempty(stri) - stri = translation.dictionary(stri); - waitbar(h.count/h.iter,h.h,stri); - else - waitbar(h.count/h.iter,h.h); - end - end; - - flushlog; - - end; - - - - %----------------------------------------------------------- - function h = mywaitbarmainstart(iter,stri,ignorelimit,waitbarfigure) - %----------------------------------------------------------- - %Overloaded functions to have the waitbar in the bottom of the main GUI - - global DATA - - if nargin<2 - myfailed('Expected two or more input arguments.'); - return; - end; - - stri = translation.dictionary(stri); - myworkon; - if length(iter)>1 - iter = length(iter); - end; - - %set parameters - h = []; - if nargin >= 4 - h.guihandle = guihandles(waitbarfigure); - elseif ~isempty(gcbf) - h.guihandle = guihandles(gcbf); - else - h.guihandle = guihandles(DATA.GUI.Segment.fig); - end - h.iter = iter; - h.count = 0; - h.oldfrac = 0; - if nargin>3 - h.ignorelimit = ignorelimit; - else - h.ignorelimit = 1; - end; - if isempty(h.ignorelimit) %Check if empty vector supplied. - h.ignorelimit = 1; %default - end; - - %initialize waitbar - if isfield(h.guihandle,'waitbaraxes') - axis(h.guihandle.waitbaraxes,'normal'); - h.guihandle.waitbarpatch = patch([0 0 0 0],[0 1 1 0],[1 1 1 1],... - 'parent',h.guihandle.waitbaraxes,'facecolor',[0 1 0]); - hold(h.guihandle.waitbaraxes,'on'); - h.guihandle.waitbarline = plot(h.guihandle.waitbaraxes,[0 0 1 1 0],[0 1 1 0 0],'g-'); - set(h.guihandle.waitbarline,'linewidth',4); - hold(h.guihandle.waitbaraxes,'off'); - xlim(h.guihandle.waitbaraxes,[0 1]); - axis(h.guihandle.waitbaraxes,'off'); - - %update waitbar - if h.iter>=h.ignorelimit - set(h.guihandle.waitbaraxes,'visible','on'); - set(h.guihandle.waitbarline,'visible','on'); - set(h.guihandle.waitbartext,'visible','on'); - set(h.guihandle.waitbarpatch,'visible','on'); - axis(h.guihandle.waitbaraxes,'off'); - set(h.guihandle.waitbartext,'backgroundcolor',DATA.GUISettings.BackgroundColor) - set(h.guihandle.waitbartext,'foregroundcolor',DATA.GUISettings.TimebarAxesColor) - set(h.guihandle.waitbartext,'string',stri); - set(h.guihandle.waitbarpatch,'xdata',[0 0 0 0]); - drawnow('expose'); - else - h = []; - end; - else - %if the waitbare axes do not exist in the current GUI, use matlabs - %waitbar instead - h.h = waitbar(0,stri); - end - - flushlog; - end - - %--------------------------------------------- - function h = mywaitbarmainupdate(h,stri) - %--------------------------------------------- - %Overloaded functions to have the waitbar in the bottom of the main GUI - - h.count = h.count+1; - if isempty(h) - return; - end; - newfrac = round(20*h.count/h.iter); - if newfrac==h.oldfrac - else - h.oldfrac = newfrac; - f = h.count/h.iter; - if isfield(h.guihandle,'waitbaraxes') - set(h.guihandle.waitbarpatch,'xdata',[0 0 f f]); - if nargin >= 3 - stri = translation.dictionary(stri); - set(h.guihandle.waitbartext,'string',stri); - end - drawnow('expose'); - else - if nargin >= 3 - stri = translation.dictionary(stri); - waitbar(h.count/h.iter,h.h,stri); - else - waitbar(h.count/h.iter,h.h); - end - end - end; - - flushlog; - - end; - - %----------------------------------- - function mywaitbarmainclose(h) - %----------------------------------- - %Overloaded functions to have the waitbar in the bottom of the main GUI - - if isempty(h) - elseif isfield(h.guihandle,'waitbaraxes') - set(h.guihandle.waitbartext,'visible','off'); - set(h.guihandle.waitbarline,'visible','off'); - set(h.guihandle.waitbarpatch,'visible','off'); - set(h.guihandle.waitbaraxes,'visible','off'); - drawnow('expose'); - clear('h'); - else - close(h.h); - end; - - flushlog; - %myworkoff; mainwaitbar only used for registration which doesn't mess - %with pointer - end; - - - %------------------------- - function copyrvendoforward - %------------------------- - %Overloaded in SegmentGUI - end - - %---------------- - function maketest - %---------------- - %Make test. Overloaded in Segment CMR GUI and RVQ GUI. - if (isequal(49,getmodule(48,'XT',[],true))) - path = myuigetdir(pwd,'Select folder for writing test record'); - if ~isequal(path,0) - internaltools.maketest('segment','allbutcallbacks',path); - end - end - end - - %----------------------------------------------------- - function [type,viewplane,technique] = imagedescription - %----------------------------------------------------- - %Define the image types, image view planes and imaging techniques - %written by Helen Soneson 2009-05-25 - %Moved by Nils Lundahl to maingui.m 2012-07-20 - %Overloaded in RVQ GUI and Segment CT GUI - - type = {'General'; - 'Cine'; - 'Late enhancement'; - 'Perfusion Rest'; - 'Perfusion Stress'; - 'Qflow'; - 'Scout'; - 'Strain FFE'; - 'Strain TFE'; - 'Strain from tagging'; - 'T1BB'; - 'T1 map' - 'T1 map Pre'; - 'T1 map Post'; - 'T2 map'; - 'T2* map'; - 'T2Stir'; - 'User defined'}; - - viewplane = {'Unspecified'; - '2CH'; - '3CH'; - '4CH'; - 'Sagittal'; - 'Coronal'; - 'Frontal'; - 'Transversal'; - 'Short-axis'; - 'Short-axis basal'; - 'Short-axis mid-ventricular'; - 'Short-axis apical'; - 'RVOT'; - 'Aorta'; - 'Pulmonalis'; - 'Vena cava inferior'; - 'User defined'}; - - technique = {'Unspecified'; - 'MRSSFP'; - 'MRDE'; - 'MRBB'; - 'MRPDW'; - 'MRSTIR'; - 'MRTOF'; - 'MRGE'; - 'NM'; - 'PT'; - 'CTheart'; - 'CT'; - 'US'; - 'User defined'}; - end - - %------------------------------------------------ - function menuoptions = getmultiplepatientsoptions - %------------------------------------------------ - %Return options for a user trying to load data from patient - %with different name. Overloaded in Segment CMR GUI and RVQ GUI. - menuoptions = {'Abort loading of new image stacks',... - 'Close previously loaded image stacks',... - 'Load all image stacks (not recommended)'}; - end - - %------------------------------- - function investigationaluselabel - %------------------------------- - %In Segment do nothing. The overloaded function in Segment CMR GUI - %displays warning message that the function is for investigational use - %only - end - - end -end \ No newline at end of file diff --git a/source/maingui.p b/source/maingui.p new file mode 100644 index 0000000..36379a7 Binary files /dev/null and b/source/maingui.p differ diff --git a/source/maintenance.fig b/source/maintenance.fig index 111a13a..4d3f93f 100644 Binary files a/source/maintenance.fig and b/source/maintenance.fig differ diff --git a/source/makeimagedicom.p b/source/makeimagedicom.p index 1a8df05..6742c80 100644 Binary files a/source/makeimagedicom.p and b/source/makeimagedicom.p differ diff --git a/source/makeisotropic.fig b/source/makeisotropic.fig new file mode 100644 index 0000000..be9c693 Binary files /dev/null and b/source/makeisotropic.fig differ diff --git a/source/makeisotropic.m b/source/makeisotropic.m new file mode 100644 index 0000000..6ac25a5 --- /dev/null +++ b/source/makeisotropic.m @@ -0,0 +1,126 @@ +function [varargout] = makeisotropic(varargin) +%Make isotropic GUI + +%Einar Heiberg + +if nargin==0 + varargin = {'init_Callback'}; +end + +macro_helper(varargin{:}); +[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard + +%-------------------------- +function init_Callback(arg) %#ok +%-------------------------- +%Init function + +global DATA SET NO + +gui = mygui('makeisotropic.fig'); + +DATA.GUI.MakeIsotropic = gui; + +%Store operation +gui.no = NO; +gui.res = [SET(NO).ResolutionX SET(NO).ResolutionY (SET(NO).SliceThickness+SET(NO).SliceGap)]; +gui.newres = median(gui.res); +gui.oldsize = [SET(NO).XSize SET(NO).YSize SET(NO).ZSize]; +gui.init3dp = false; %if true init 3dp after makeisotropic operation + +if nargin>0 + if isequal(arg,'init3DP') + gui.init3dp = true; + end +end + +update; + +%-------------- +function update +%-------------- +global DATA + +gui = DATA.GUI.MakeIsotropic; + +gui.newsize = round(gui.oldsize.*gui.res/gui.newres); +set(gui.handles.resolutiontext,'String',sprintf('%0.3g*%0.3g*%0.3g',gui.res(1),gui.res(2),gui.res(3))); +set(gui.handles.resolutionedit,'String',sprintf('%0.3g',gui.newres)); +set(gui.handles.sizetext,'String',sprintf('%d*%d*%d',gui.oldsize(1),gui.oldsize(2),gui.oldsize(3))); +set(gui.handles.numvoxelstext,'String',sprintf('%d (100 %%)',prod(gui.oldsize))); +set(gui.handles.newsizetext,'String',sprintf('%d*%d*%d',gui.newsize(1),gui.newsize(2),gui.newsize(3))); +set(gui.handles.newnumvoxelstext,'String',sprintf('%d (%d %%)',prod(gui.newsize),round(100*prod(gui.newsize)/prod(gui.oldsize)))); +gui.out = false; + +%------------------------------- +function resolutionedit_Callback %#ok +%------------------------------- +%edit box + +global DATA + +gui = DATA.GUI.MakeIsotropic; + +s = get(gui.handles.resolutionedit,'String'); +v = str2double(s); +if ~isnan(v) + gui.newres = v; + update; +else + update; +end + +%------------------------------ +function makeisotropic_Callback %#ok +%------------------------------ +%Computes to isotropic, uses routines in tools + +global DATA + +gui = DATA.GUI.MakeIsotropic; + +numel = prod(gui.newsize); +if numel>(512*512*768) + if yesno('Very large volume size. Abort?') + return; + end +end + +myworkon; + +if abs(gui.res(3)/gui.newres-1)>1e-4 + %resample slices + f = gui.res(3)/gui.newres; + disp('Upsamling slices.'); + tools('upsampleslices_Callback',f); +end + +if abs(gui.res(1)/gui.newres-1)>1e-4 + %resample inplane + f = gui.res(1)/gui.newres; + disp('Upsamling in plane.'); + tools('upsampleimage_Callback',f,gui.no); +end + +if gui.init3dp + DATA.Handles.toggleiconholder.indent('ribbon3dp',1) +end + +myworkoff; + +close_Callback; + +%---------------------- +function close_Callback +%---------------------- +%Close the gui + +global DATA + +try + gui = DATA.GUI.MakeIsotropic; + delete(gui.fig); +catch +end +DATA.GUI.MakeIsotropic = []; + diff --git a/source/manualedit.fig b/source/manualedit.fig index 3f8baec..e6b28c6 100644 Binary files a/source/manualedit.fig and b/source/manualedit.fig differ diff --git a/source/mar.p b/source/mar.p index cc2478e..aa065f9 100644 Binary files a/source/mar.p and b/source/mar.p differ diff --git a/source/matlab2vtk.m b/source/matlab2vtk.m index 1209c21..6e1f6cf 100644 --- a/source/matlab2vtk.m +++ b/source/matlab2vtk.m @@ -34,7 +34,7 @@ function matlab2vtk(pathname, filename, datastruct) disp(rotation); disp(delta); disp('------'); - end; + end function [L, P, H, delta1, delta2, delta3, vx, vy, vz] = get_lph(partno) dirdim = double(datastruct(partno).DirDim); dd1 = dirdim(:,1); @@ -68,13 +68,13 @@ function matlab2vtk(pathname, filename, datastruct) if voxspace(1) < 0.0 vx = vx*-1; - end; + end if voxspace(2) < 0.0 vy = vy*-1; - end; + end if voxspace(3) < 0.0 vz = vz*-1; - end; + end clear i j k L = L(:); P = P(:); @@ -82,7 +82,7 @@ function matlab2vtk(pathname, filename, datastruct) delta1 = datastruct(partno).Delta(1); delta2 = datastruct(partno).Delta(2); delta3 = datastruct(partno).Delta(3); - end; + end function [x1, x2, y1, y2, z1, z2, delta1, delta2, delta3, L, P, H, vx, vy, vz] = get_whole_extents_of_part(partno) [L, P, H, delta1, delta2, delta3, vx, vy, vz] = get_lph(partno); @@ -92,7 +92,7 @@ function matlab2vtk(pathname, filename, datastruct) y2 = datastruct(partno).Size(2)-1; z1 = 0; z2 = datastruct(partno).Size(3)-1; - end; + end function export_vector_array(partno, geofilefid, current_time) fprintf(geofilefid, '\t\t\t\t'); @@ -100,13 +100,13 @@ function export_vector_array(partno, geofilefid, current_time) fprintf(geofilefid, '% f ', datastruct(partno).Data(:, :, :, current_time, 2)); fprintf(geofilefid, '% f ', datastruct(partno).Data(:, :, :, current_time, 3)); fprintf(geofilefid, '\n'); - end; + end function export_2d_magnitude_array(partno, geofilefid, current_time) fprintf(geofilefid, '\t\t\t\t'); fprintf(geofilefid, '% f ', datastruct(partno).Data(:, :, :, current_time, 1)); fprintf(geofilefid, '\n'); - end; + end function export_points(L, P, H) fprintf(geofilefid, '\t\t\t\n'); @@ -117,28 +117,28 @@ function export_points(L, P, H) fprintf(geofilefid, '% f ', H); fprintf(geofilefid, '\n'); fprintf(geofilefid, '\t\t\t\n'); - end; + end function export_magnitude_array(partno, geofilefid, current_time, originalDelta) fprintf(geofilefid, '\t\t\t\t'); x = datastruct(partno).Data(:, :, :, current_time, 2); if originalDelta(2) < 0 x = flip(z, 2); - end; + end y = datastruct(partno).Data(:, :, :, current_time, 1); if originalDelta(1) < 0 y = flip(y, 1); - end; + end z = datastruct(partno).Data(:, :, :, current_time, 3); if originalDelta(3) < 0 z = flip(z, 3); - end; + end length = sqrt(x.*x+y.*y+z.*z); length = permute(length,[2 1 3]); fprintf(geofilefid, '% f ', length); fprintf(geofilefid, '\n'); - end; + end function export_maximum_magnitude_array(partno, geofilefid, current_time) fprintf(geofilefid, '\t\t\t\t'); @@ -155,9 +155,9 @@ function export_maximum_magnitude_array(partno, geofilefid, current_time) outValues(outValuesIndex) = maximumvalue; outValuesIndex = outValuesIndex+1; fprintf(geofilefid, '%f ', maximumvalue); - end; - end; - end; + end + end + end x = datastruct(partno).Data(:, :, :, current_time, 1); y = datastruct(partno).Data(:, :, :, current_time, 2); z = datastruct(partno).Data(:, :, :, current_time, 3); @@ -165,7 +165,7 @@ function export_maximum_magnitude_array(partno, geofilefid, current_time) fprintf(geofilefid, '% f ', outValues); clear outValues; fprintf(geofilefid, '\n'); - end; + end function export_parts(partno, geofilefid, current_time, originalDelta) fprintf(geofilefid, '\t\t\t\n'); @@ -177,10 +177,10 @@ function export_parts(partno, geofilefid, current_time, originalDelta) %export_vector_array(partno, geofilefid, current_time); %export_magnitude_array(partno, geofilefid, current_time, originalDelta); export_maximum_magnitude_array(partno, geofilefid, current_time); - end; + end fprintf(geofilefid, '\t\t\t\n'); %export_points(L, P, H); - end; + end numparts = length(datastruct); %Create and open the file @@ -189,7 +189,7 @@ function export_parts(partno, geofilefid, current_time, originalDelta) if isequal(casefilefid,-1) error(sprintf('Could not open %s for output.',[pathname filesep filename ... '.case'])); - end; + end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -218,7 +218,7 @@ function export_parts(partno, geofilefid, current_time, originalDelta) geofilefid = fopen(newname,'w'); % geofilefid = fopen(newname,'wb'); if isequal(geofilefid,-1) error(sprintf('Could not open %s for output.',newname)); - end; + end fprintf(geofilefid,'\n'); fprintf(geofilefid,'\n'); @@ -228,7 +228,7 @@ function export_parts(partno, geofilefid, current_time, originalDelta) fprintf(geofilefid, '\t\t\n', x1, x2, y1, y2, z1, z2); export_parts(partno, geofilefid, current_time, originalDelta); fprintf(geofilefid, '\t\t\n'); - end; + end fprintf(geofilefid, '\t\n'); fprintf(geofilefid,'\n'); fclose(geofilefid); diff --git a/source/matsorter.p b/source/matsorter.p index 580e579..30d0b45 100644 Binary files a/source/matsorter.p and b/source/matsorter.p differ diff --git a/source/memorybasket.p b/source/memorybasket.p index f30b85a..5ca1b0d 100644 Binary files a/source/memorybasket.p and b/source/memorybasket.p differ diff --git a/source/mergestacks.fig b/source/mergestacks.fig index 5f7fd3a..52924d5 100644 Binary files a/source/mergestacks.fig and b/source/mergestacks.fig differ diff --git a/source/mergestacks.m b/source/mergestacks.m index 36d0d9c..ee3ffb1 100644 --- a/source/mergestacks.m +++ b/source/mergestacks.m @@ -8,12 +8,13 @@ %Minor bugfixing by Einar Heiberg -global SET +global SET DATA if nargin < 1 %Launch GUI - fig = openfig('mergestacks.fig'); - handles = guihandles(fig); + gui = mygui('mergestacks.fig'); + DATA.GUI.MergeStacks = gui; + handles = gui.handles; stackc = cell(1,numel(SET)); for no = 1:numel(SET) stackc{no} = sprintf('%d. %s, %s',no,SET(no).ImageType,SET(no).ImageViewPlane); @@ -83,7 +84,7 @@ else domerge(nos); end - segment('switchtoimagestack',numel(SET),true); + viewfunctions('setview',1,1,numel(SET),{'one'})%segment('switchtoimagestack',numel(SET),true); flushlog; close(handles.figure1); end @@ -127,10 +128,10 @@ function domerge(nostomerge,force) area1 = SET(no1).ResolutionX*SET(no1).ResolutionY; area2 = SET(no2).ResolutionX*SET(no2).ResolutionY; if ~yesno(dprintf('Not the same ResolutionX or Resolution Y, difference in percentage of area in pixels is: %0.5g %%. This will introduce and error in the quantification, proceed?',... - 100*min([area1 area2])/max([area1 area2]))); + 100*min([area1 area2])/max([area1 area2]))) return; - end; - end; + end + end thesenos = [no1 no2]; if all([SET(thesenos).ZSize] > 1) @@ -272,7 +273,7 @@ function domerge(nostomerge,force) else %If not single then just add, assume CT or true count values. setstruct.IM(xext,yext,:,zext) = set2.IM; - end; + end setstruct.ZSize = newzsz; setstruct.XSize = max(SET(no1).XSize,set2.XSize); setstruct.YSize = max(SET(no1).YSize,set2.YSize); @@ -284,12 +285,12 @@ function domerge(nostomerge,force) %no1 is empty but no2 is not viability('viabilityreset_Callback','weighted',no1); setstruct.Scar = SET(no1).Scar; - end; + end if ~isempty(setstruct.Scar) && isempty(set2.Scar) %no1 have scar but no2 not viability('viabilityreset_Callback','weighted',no2); setstruct.Scar = SET(no2).Scar; - end; + end if not(isempty(set2.Scar)) %Assign if exist in set2 @@ -300,26 +301,26 @@ function domerge(nostomerge,force) %SET(no).Scar.Undo = SET(no).Scar.Undo(:,:,ind); setstruct.Scar.MyocardMask(xext,yext,zext) = set2.Scar.MyocardMask; setstruct.Scar.NoReflow(xext,yext,zext) = set2.Scar.NoReflow; - end; + end %MaR if isempty(setstruct.MaR) && ~isempty(set2.MaR) %no1 is empty but no2 is not mar('initdefault',no1); setstruct.MaR = SET(no1).MaR; - end; + end if ~isempty(setstruct.MaR) && isempty(set2.MaR) %no1 have mar but no2 not mar('initdefault',no2); setstruct.MaR = SET(no2).MaR; - end; + end if not(isempty(setstruct.MaR)) setstruct.MaR.Auto(xext,yext,:,zext) = set2.MaR.Auto; setstruct.MaR.Result(xext,yext,:,zext) = set2.MaR.Result; setstruct.MaR.Manual(xext,yext,:,zext) = set2.MaR.Manual; setstruct.MaR.MyocardMask(xext,yext,:,zext) = set2.MaR.MyocardMask; - end; + end %Merge contours contfields = {'Endo','Epi','RVEndo','RVEpi',... @@ -373,18 +374,18 @@ function domerge(nostomerge,force) for loop=1:set2.RoiN set2.Roi(loop).Z = zext(set2.Roi(loop).Z); setstruct.Roi = [setstruct.Roi set2.Roi(loop)]; - end; + end setstruct.RoiN = setstruct.RoiN + set2.RoiN; if setstruct.RoiN>0 setstruct.RoiCurrent = 1; else setstruct.RoiCurrent = []; - end; + end % Measure for loop=1:numel(set2.Measure) set2.Measure(loop).Z = zext(set2.Measure(loop).Z); - end; + end setstruct.Measure = [setstruct.Measure set2.Measure]; %Set no of generated image stack and remove links @@ -418,6 +419,8 @@ function domerge(nostomerge,force) drawfunctions('drawthumbnails'); +close_Callback; + %-------------------------------------------------------------------- function initwhichstack_Callback(nostomerge) @@ -425,10 +428,11 @@ function initwhichstack_Callback(nostomerge) global DATA SET %Launch GUI -DATA.GUI.whichstack = openfig('whichstack.fig'); -handles = guihandles(DATA.GUI.whichstack); +gui = mygui('whichstack.fig'); +DATA.GUI.WhichStack = gui; +handles = gui.handles; %DATA.GUI.whichstack.handles=handles; -DATA.GUI.whichstack.nostomerge=nostomerge; +handles.nostomerge=nostomerge; stackc = cell(1,numel(nostomerge)); counter=1; for no = nostomerge @@ -456,12 +460,16 @@ function initwhichstack_Callback(nostomerge) end NO=oldNO; close(gcbf) -%DATA.GUI.whichstack.proceed=1; -%DATA.GUI.whichstack=[]; -% %-------------------------------------------- -% function close_Callback -% %-------------------------------------------- -% global DATA -% close(gcbf) -%DATA.GUI.whichstack.proceed=0; +%---------------------- +function close_Callback +%---------------------- +global DATA + +try + DATA.GUI.MergeStacks = close(DATA.GUI.MergeStacks); +catch me + mydispexception(me)%#ok + DATA.GUI.MergeStacks =[]; + delete(gcbf); +end diff --git a/source/mesh2stl.m b/source/mesh2stl.m index 2b82102..f46d072 100644 --- a/source/mesh2stl.m +++ b/source/mesh2stl.m @@ -34,26 +34,26 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) if nargin<8 myfailed('Too few input arguments.'); return; - end; + end fidsupplied = false; -end; +end if isempty(fignr) doplot = false; else doplot = true; c = rand(1,1); -end; +end if size(x,1)<2 disp('Only one slice, ignored'); -end; +end %If should plot if doplot figure(fignr); hold on; -end; +end %Open the file if ~fidsupplied @@ -61,13 +61,13 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) if isequal(fid,-1) myfailed(dprintf('Could not open the file %s for writing.',[pathname filename])); return; - end; -end; + end +end %Start the file if ~fidsupplied fprintf(fid,'solid segment stl \n'); -end; +end n = 1:size(x,2); %Vector 1-n elements along the contour @@ -108,16 +108,16 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) switched = true; else switched = false; - end; + end %Resample row1 according to length newn = round(drow1/resolution); if newn<1 newn = 1; - end; + end if newn>size(x,2) newn = size(x,2); - end; + end ni = linspace(1,size(x,2)-(size(x,2)-1)/newn,newn); %As the mesh is cyclic it should not interpolate to the end of the line. xrow1 = interp1(n,xrow1,ni); yrow1 = interp1(n,yrow1,ni); @@ -127,10 +127,10 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) newn = round(drow2/resolution); if newn<1 newn = 1; - end; + end if newn>size(x,2) newn = size(x,2); - end; + end ni = linspace(1,size(x,2)-(size(x,2)-1)/newn,newn); xrow2 = interp1(n,xrow2,ni); yrow2 = interp1(n,yrow2,ni); @@ -161,7 +161,7 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) normal = -cross([x2-x1,y2-y1,z2-z1],[x3-x1,y3-y1,z3-z1]); if switched normal = -normal; - end; + end fprintf(fid, 'facet normal %f %f %f \n', normal ); fprintf(fid, 'outer loop \n'); fprintf(fid, 'vertex %f %f %f \n', x1,y1,z1); @@ -173,7 +173,7 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) if doplot %Graphical update patch([x1;x2;x3],[y1;y2;y3],[z1;z2;z3],c*ones(3,1)); - end; + end %Check if not redundant triangle if ~isequal(closestpoint(nextind(loop)),closestpoint(nextind(loop+1))) @@ -187,7 +187,7 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) normal = -cross([x2-x4,y2-y4,z2-z4],[x4-x4,y4-y3,z4-z3]); if switched normal = -normal; - end; + end fprintf(fid, 'facet normal %f %f %f \n', normal ); fprintf(fid, 'outer loop \n'); fprintf(fid, 'vertex %f %f %f \n', x2,y2,z2); @@ -199,11 +199,11 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) if doplot %Graphical update patch([x2;x4;x3],[y2;y4;y3],[z2;z4;z3],c*ones(3,1)); - end; + end - end; %If not this triangle is the same as the previous one + end %If not this triangle is the same as the previous one - end; %loop over number of points in the largest layer + end %loop over number of points in the largest layer %Close apex if isequal(row,size(x,1)-1) && closeapex @@ -226,10 +226,10 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) newn = round(drow2/resolution); if newn<1 newn = 1; - end; + end if newn>size(x,2) newn = size(x,2); - end; + end ni = linspace(1,size(x,2)-(size(x,2)-1)/newn,newn); xrow2 = interp1(n,xrow2,ni); yrow2 = interp1(n,yrow2,ni); @@ -267,19 +267,19 @@ function mesh2stl(x,y,z,resolution,closeapex,fignr,pathname,filename) if doplot %Graphical update patch([x1;x2;x3],[y1;y2;y3],[z1;z2;z3],c*ones(3,1)); - end; + end - end; %Loop over points when closing - end; %If indeed to be closed - end; %Close apex and last row -end; %Loop over rows + end %Loop over points when closing + end %If indeed to be closed + end %Close apex and last row +end %Loop over rows %End the file if ~fidsupplied fprintf(fid,'endsolid stl\n'); fclose(fid); -end; +end if doplot hold off; -end; +end diff --git a/source/motionfunctions.m b/source/motionfunctions.m new file mode 100644 index 0000000..d5451c2 --- /dev/null +++ b/source/motionfunctions.m @@ -0,0 +1,549 @@ + function varargout = motionfunctions(varargin) +% Functions for cursor motion +% Klas +%Invoke subfunction + +macro_helper(varargin{:}); %future macro recording use +if (nargout) + [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard +else + feval(varargin{:}); % FEVAL switchyard +end + +%--------------------------- +function select_motion(panel) %#ok +%--------------------------- +%Function that highlights the selected panel if montage also highlight the frame +global DATA SET + +no = DATA.ViewPanels(panel); +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +slice = viewfunctions('clickedslice',panel,x,y); + +%clicked in black area of montage +if isempty(slice) + return +end + +if slice == SET(no).CurrentSlice + SET(no).StartSlice = slice; + SET(no).EndSlice = slice; +elseif slice > SET(no).CurrentSlice + SET(no).EndSlice = slice; +elseif slice < SET(no).CurrentSlice + SET(no).StartSlice = slice; +end + +drawfunctions('drawselectedslice',panel) + +%---------------------------------------------- +function [contrastout,brightnessout] = contrast_motion(panel,slice,xstart,ystart,xsize,ysize) %#ok +%---------------------------------------------- +%motion function for contrast image +global DATA SET + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +%we need to update the delta contrast and delta brightness based on dx and +%dy +deltacontrast = (x-xstart)/xsize; +deltabrightness = -(y-ystart)/ysize; + +no = DATA.ViewPanels(panel); + +if ~isempty(SET(no).IntensityScaling) && ~isempty(SET(no).IntensityMapping) + [window,level] = calcfunctions('con2win',... + SET(no).IntensityMapping.Contrast+deltacontrast,... + SET(no).IntensityMapping.Brightness+deltabrightness,no); + [contrast,brightness] = calcfunctions('win2con',window,level,no); +else + contrast = SET(no).IntensityMapping.Contrast+deltacontrast; + brightness = SET(no).IntensityMapping.Brightness+deltabrightness; +end + +if any(strcmp(DATA.ViewPanelsType{panel},{'montage','montagerow','montagesegmented'})) + if strcmp(DATA.ViewPanelsType{panel},'montagesegmented') + segmentedonly=true; + else + segmentedonly=false; + end + im = calcfunctions('calcmontageviewim', ... + no,fliplr(DATA.ViewPanelsMatrix{panel}),segmentedonly,calcfunctions('returnmapping',no),contrast,brightness,[],SET(no).CurrentTimeFrame); + set(DATA.Handles.imagehandles(panel),'cdata',squeeze(im)); +else + %update the image with the new contrast and brightness settings + im = calcfunctions('remapuint8',SET(no).IM(:,:,SET(no).CurrentTimeFrame,slice),no,... + calcfunctions('returnmapping',no),contrast,brightness); + scale = viewfunctions('getscale',panel); + im = imresize(im,scale); + if ~isempty(SET(no).Colormap)|| ndims(im)==3 + set(DATA.Handles.imagehandles(panel),'cdata',im); + else + set(DATA.Handles.imagehandles(panel),'cdata',cat(3,im,im,im)); + end + + + %update colorbar +% if DATA.GUISettings.ShowColorbar +% h = colorbar(DATA.Handles.imageaxes(panel),'EastOutside'); +% if isempty(SET(no).Colormap) +% colormap(h,'gray'); +% else +% colormap(h,SET(no).Colormap); +% end +% h.Color = DATA.GUISettings.ForegroundColor; +% [win level]=calcfunctions('con2win',SET(no).IntensityMapping.Contrast, SET(no).IntensityMapping.Brightness) +% set(DATA.Handles.imageaxes(panel),'CLim',[(level-win/2) (level+win/2)]) +% end +% + +end + +%update colorbar +if DATA.GUISettings.ShowColorbar + createfunctions('addcolorbar',panel,contrast, brightness) +% h = colorbar(DATA.Handles.imageaxes(panel),'East'); +% [win, level]=calcfunctions('con2win',contrast, brightness); +% set(DATA.Handles.imageaxes(panel),'CLim',[(level-win/2) (level+win/2)]) +% if isempty(SET(no).Colormap) +% colormap(h,'gray'); +% else +% colormap(h,SET(no).Colormap); +% end +% h.Color = DATA.GUISettings.ForegroundColor; + +end +% +% set(DATA.Handles.imagehandles(panel),'cdata',cat(3,im,im,im)); + +if nargout == 2 + brightnessout = brightness; + contrastout = contrast; +end + +%---------------------------------------------- +function [Xout, Yout] = crop_motion(panel,xstart,ystart) +%---------------------------------------------- +%Motion function for cropping. + +global DATA + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +%This always makes a box +X = [xstart,xstart,x,x,xstart]; +Y = [ystart,y,y,ystart,ystart]; + +DATA.CursorX = X; +DATA.CursorY = Y; + +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + +if nargout == 2 + Xout = X; + Yout = Y; +end + +%---------------------------------------------- +function measure_motion(panel,pointind) %#ok +%---------------------------------------------- +%Motion function for measures. Has panel and point index of the currently dragged +%measurement as input. + +global DATA SET NO + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +DATA.CursorX(pointind) = x; +DATA.CursorY(pointind) = y; +DATA.CursorZ(pointind) = SET(NO).CurrentSlice; + +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + + +%---------------------------------------------- +function putroi_motion(panel) +%---------------------------------------------- +%This function expands a balloon using otsu and polar transform +global DATA + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +DATA.CursorX = DATA.CursorX-mean(DATA.CursorX)+x; +DATA.CursorY = DATA.CursorY-mean(DATA.CursorY)+y; + +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + + +%---------------------------------------------- +function interp_motion(panel,type,sliceind,pointind) %#ok +%---------------------------------------------- +%Motion function input is panel type sliceind and pointind. The types handled here +%are {EndoInterp,EpiInterp,RVendoInterp,RVepiInterp}. The indexes are +%determined in the buttondown so that the correct point is shifted. + +global DATA SET +no = DATA.ViewPanels(panel); + +%get closest interpolation point +[yclick,xclick] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +scale = viewfunctions('getscale',panel); +slice = viewfunctions('clickedslice',panel,yclick,xclick); +slices = viewfunctions('slicesinpanel',panel); + +%normalize clicked position to contour domain +[yl,xl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slices == slice,1)); +x = xclick/scale - (xl-1)*SET(no).XSize; +y = yclick/scale - (yl-1)*SET(no).YSize; + +SET(no).([type,'X']){SET(no).CurrentTimeFrame,sliceind}(pointind) = x; +SET(no).([type,'Y']){SET(no).CurrentTimeFrame,sliceind}(pointind) = y; + +if SET(no).([type(1:end-6),'InterpOngoing']) + numinterppoints = length(SET(no).([type,'X']){SET(no).CurrentTimeFrame,slice}); + numpoints = floor(DATA.NumPoints/15)*(numinterppoints-1); + if numpoints > DATA.NumPoints + numpoints = DATA.NumPoints; + end +else + numpoints = DATA.NumPoints; +end + +%here we need to interpolate and store curve into contours +%removes duplicate points and resamples the contour +[x,y] = calcfunctions('resamplecurve',SET(no).([type,'X']){SET(no).CurrentTimeFrame,sliceind},... + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,sliceind},numpoints-1); + +%write the results back to the SET struct +if length(x)>2 + switch type + case 'Roi' + %would be nice to introduce RoiInterpX... + otherwise + if SET(no).([type(1:end-6),'InterpOngoing']) + expectedlength = length(SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,slice)); + if numpoints < expectedlength + % fill up with NaNs + x = cat(2,x,nan(1,expectedlength-numpoints)); + y = cat(2,y,nan(1,expectedlength-numpoints)); + end + end + SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,sliceind)= [x,x(1)]; + SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,sliceind)= [y,y(1)]; + drawfunctions('drawcontours',panel,type(1:end-6)) + end +end +drawfunctions('drawinterp',panel,type) + +%--------------------------------- +function glarotatehandle_Motion(panel) +%--------------------------------- +%Motion fcn for using GLA view rotation handle +global SET DATA + +no = DATA.ViewPanels(panel); +scale = viewfunctions('getscale',panel); + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +x = x/scale; +y = y/scale; +glaangle = mod(atan2(SET(no).ResolutionX*(y-SET(no).HLA.slice), ... + SET(no).ResolutionY*(x-SET(no).VLA.slice))+pi/2,pi)-pi/2; + +%We draw a line with markers the endpoint markers can not be seen as they +%are outside the field of view +DATA.Handles.cursor.XData = scale*(x+1000/SET(no).ResolutionY*cos(glaangle)*[1 0 -1]); +DATA.Handles.cursor.YData = scale*(y+1000/SET(no).ResolutionX*sin(glaangle)*[1 0 -1]); +%------------------------------ +function [Xout,Yout,incr] = scale_motion(panel,startrad) %#ok +%----------------------- +global DATA + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system + +X = DATA.CursorX; +Y = DATA.CursorY; + +xc = mean(X); +yc = mean(Y); +a = norm([x,y]-[xc,yc]); + +incr = a/startrad; + +X = xc+(X-xc)*incr; +Y = yc+(Y-yc)*incr; + +DATA.Handles.cursor.YData = X; +DATA.Handles.cursor.XData = Y; + +if nargout>0 + Xout=X; + Yout=Y; +end + +%------------------------------ +function [Xout,Yout] = translate_motion(panel,xstart,ystart) %#ok +%----------------------- +global DATA + +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel));%this needs to transformed to the stored coordinate system +X = DATA.CursorX-xstart+x; +Y = DATA.CursorY-ystart+y; + +DATA.Handles.cursor.YData = X; +DATA.Handles.cursor.XData = Y; + +if nargout>0 + Xout = X; + Yout = Y; +end + +%-------------------------------- +function viewportpoints_motion(ind) %#ok +%-------------------------------- +%Motion function for viewport and points + +global DATA SET NO + +coord = getclickedcoord(DATA.LevelSet.ViewPort); + +if ~isnan(coord(1)) + x = coord(1)+DATA.LevelSet.Box.xmin-1; %This adds if the the volume is cropped + y = coord(2)+DATA.LevelSet.Box.ymin-1; + z = coord(3)+DATA.LevelSet.Box.zmin-1; + + SET(NO).Point.X(ind) = x; + SET(NO).Point.Y(ind) = y; + SET(NO).Point.Z(ind) = z; + +end + +segment3dp.tools('addpointstoviewport'); + +%See if we should update the line +if ~isempty(SET(NO).Line3D.Points) + if ismember(ind,SET(NO).Line3D.Points{1}) + segment3dp.linetools('createline','',SET(NO).Line3D.Points{1}); %Later possibility to have more lines + end +end + +%---------------------------------------------- +function point_motion(panel) +%---------------------------------------------- +%New motion function that handles points. + +global DATA + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +%plot clicked position +DATA.Handles.cursor.XData = x; +DATA.Handles.cursor.YData = y; + +%---------------------------------------------- +function pan_motion(panel,xwstart,ywstart) %#ok +%---------------------------------------------- +%New motion function for panning. Uses cursorX and cursor Y to store the +%initial positions of XLim and YLim + +global DATA SET + +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +xw = x-DATA.Handles.imageaxes(panel).XLim(1); +yw = y-DATA.Handles.imageaxes(panel).YLim(1); + +dx = xw - xwstart; +dy = yw - ywstart; + +%move +xc = DATA.CursorX - dx; +yc = DATA.CursorY - dy; + +%this is to halt execution assert that the above is set before running +panelslinked = find(ismember(DATA.ViewPanels,SET(DATA.ViewPanels(panel)).Linked)); +paneltype = DATA.ViewPanelsType{DATA.CurrentPanel}; +if ismember(paneltype,{'trans3DP','sag3DP','cor3DP'}) + panelslinked = [DATA.CurrentPanel viewfunctions('findspeedim')]; +end +for actpanel = panelslinked + set(DATA.Handles.imageaxes(actpanel),'XLim' ,xc,'YLim',yc) +end + +drawfunctions('drawselectedframe',panel); + +%---------------------------------------------- +function pen_motion(panel) %#ok +%---------------------------------------------- +%New motion function that handles all the different pen tools. + +global DATA +[x,y] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); + +DATA.CursorX = cat(1,DATA.CursorX,x); +DATA.CursorY = cat(1,DATA.CursorY,y); + +DATA.Handles.cursor.XData = DATA.CursorX; +DATA.Handles.cursor.YData = DATA.CursorY; + +%-------------------------- +function select3dp_motion %#ok +%-------------------------- +%Motion function for select +global DATA + +segment3dp.tools('storeclickedposition'); + +%segment3dp.tools('update3DP') +for p = find(DATA.ViewPanels) + if ~isequal(DATA.ViewPanelsType{p},'viewport') %no need to draw viewport + drawfunctions('drawpanel',p); + end +end + +for loop = 1:length(DATA.ViewPanels) + if ~isequal(DATA.ViewPanelsType{loop},'speedim') + drawfunctions('drawtext',loop); + end +end + +%-------------------------- +function fastmarching_motion %#ok +%-------------------------- +%Motion function for graphical updates using fastmarching tool +global DATA SET NO + +if DATA.Run + return +end + +[r,g,b] = segment3dp.tools('getclickedposition3DP'); + +SET(NO).LevelSet.View.RSlice = r; +SET(NO).LevelSet.View.GSlice = g; +SET(NO).LevelSet.View.BSlice = b; + +%Convert to Segment indices +[x,y,z] = segment3dp.tools('rgb2xyz',r,g,b); + +%Extrac arrival time at mouse click +arrivaltime = DATA.LevelSet.ArrivalTime(x,y,z); + +if isnan(arrivaltime) + arrivaltime = max(DATA.LevelSet.ArrivalTime(:)); +end + +imh_r = DATA.Handles.imagehandles(strcmp(DATA.ViewPanelsType,'trans3DP')); +imh_g = DATA.Handles.imagehandles(strcmp(DATA.ViewPanelsType,'sag3DP')); +imh_b = DATA.Handles.imagehandles(strcmp(DATA.ViewPanelsType,'cor3DP')); +%Red +im = segment3dp.tools('getimage','r'); +bw = segment3dp.tools('getimagehelper',SET(NO).LevelSet.BW,'r')>uint8(127) | (segment3dp.tools('getimagehelper',DATA.LevelSet.ArrivalTime,'r')uint8(127) | (segment3dp.tools('getimagehelper',DATA.LevelSet.ArrivalTime,'g')uint8(127) | (segment3dp.tools('getimagehelper',DATA.LevelSet.ArrivalTime,'b') +%---------------------- +%Manual draw + +global SET NO DATA +persistent counter + +if isempty(counter) + counter = 0; +end + +%second input asserts update of all panels +if nargin<2 + update=0; +end + +[r,g,b] = segment3dp.tools('getclickedposition3DP'); + +[x,y,z] = segment3dp.tools('rgb2xyz',r,g,b); + +%Old code to ensure it +%Check if valid position & move +%x = min(max(round(x),SET(NO).LevelSet.Pen.XSize),SET(NO).XSize-SET(NO).LevelSet.Pen.XSize); +%y = min(max(round(y),SET(NO).LevelSet.Pen.YSize),SET(NO).YSize-SET(NO).LevelSet.Pen.YSize); +%z = min(max(round(z),SET(NO).LevelSet.Pen.ZSize),SET(NO).ZSize-SET(NO).LevelSet.Pen.ZSize); + +x = min(max(round(x),1),SET(NO).XSize); +y = min(max(round(y),1),SET(NO).YSize); +z = min(max(round(z),1),SET(NO).ZSize); + +%Convert back to RGB for storage +[r,g,b] = segment3dp.tools('xyz2rgb',x,y,z); +SET(NO).LevelSet.View.RSlice = r; +SET(NO).LevelSet.View.GSlice = g; +SET(NO).LevelSet.View.BSlice = b; + +%Find index +xind = SET(NO).LevelSet.Pen.X+x; +yind = SET(NO).LevelSet.Pen.Y+y; +zind = SET(NO).LevelSet.Pen.Z+z; + +%Find inside positions +logind = ... + (xind>0) & (xind<=SET(NO).XSize) & ... + (yind>0) & (yind<=SET(NO).YSize) & ... + (zind>0) & (zind<=SET(NO).ZSize); + +%Remove outside +xind = xind(logind); +yind = yind(logind); +zind = zind(logind); + +try + motionindex = sub2ind([SET(NO).XSize SET(NO).YSize SET(NO).ZSize],xind,yind,zind); +catch + disp('outside image'); + set(DATA.fig,'windowbuttonmotionfcn',@DATA.toggleplaceholdermotion) + return; +end + +if isequal(tool,'localthreshold') + %Normal draw/erase + SET(NO).LevelSet.BW(motionindex) = segment3dp.tools('calcthreshold3DP',SET(NO).LevelSet.SpeedIM(motionindex)); +else + switch DATA.CurrentTool + case 'rubber' + DATA.LevelSet.Man(motionindex) = int8(-1); + SET(NO).LevelSet.BW(motionindex) = min(SET(NO).LevelSet.BW(motionindex),SET(NO).LevelSet.Pen.Value(logind)); + case 'draw' + DATA.LevelSet.Man(motionindex) = int8(1); + SET(NO).LevelSet.BW(motionindex) = max(SET(NO).LevelSet.BW(motionindex),SET(NO).LevelSet.Pen.Value(logind)); + end +end + +DATA.toggleplaceholdermotion + +%For speed sake only update every 4th +counter = mod(counter+1,8); +if counter==1 || update + DATA.LevelSet.bwupdated = true; + segment3dp.tools('update3DP') + %segment3dp.tools('bwupdated'); %this is way to slow! +else + drawfunctions('drawimages',DATA.CurrentPanel) +end + +segment3dp.tools('updatergbsliders'); + + diff --git a/source/movescu.exe b/source/movescu.exe index 5222a17..d95e294 100644 Binary files a/source/movescu.exe and b/source/movescu.exe differ diff --git a/source/mybrowser.m b/source/mybrowser.m index ebdf4da..13fd1d8 100644 --- a/source/mybrowser.m +++ b/source/mybrowser.m @@ -1,9 +1,21 @@ -function mybrowser(url) +function mybrowser(url,browser) %MYBROWSER(URL) Opens an URL platform independent. %Jane Sjögren global DATA +if nargin == 1 + try + browser = DATA.Pref.WebBrowser; + catch + mywarning(dprintf('Could not open default browser.\nPlease open your browser and go to\n%s',url)) + return + end +end -command=['"' DATA.Pref.WebBrowser '" "' url '"']; -system(command); -flushlog; \ No newline at end of file +try + command=['"' browser '" "' url '"']; + system(command); + flushlog; +catch + mywarning(dprintf('Could not open default browser.\nPlease open your browser and go to\n%s',url)) +end diff --git a/source/mycat.m b/source/mycat.m index 7c14811..a9bd530 100644 --- a/source/mycat.m +++ b/source/mycat.m @@ -1,6 +1,4 @@ -%------------------------------------------------------------------------- function catvect=mycat(varargin) -%------------------------------------------------------------------------- %Same as cat, but removes nans and converts them to handles. Fix bug with %R2015 %Klas Berggren, comments by Einar Heiberg @@ -8,11 +6,11 @@ if nargin==0 myfailed('Expects at least one input argument.'); return; -end; +end for loop = 1:nargin varargin{loop} = double(varargin{loop}); -end; +end catvect = cat(varargin{:}); catvect = catvect(~isnan(catvect)); \ No newline at end of file diff --git a/source/mycopyfile.m b/source/mycopyfile.m index 35247c9..f984f8e 100644 --- a/source/mycopyfile.m +++ b/source/mycopyfile.m @@ -14,10 +14,10 @@ varargout = cell(1,nargout); if nargout>0 varargout{1} = sucess; -end; +end if nargout>1 varargout{2} = message; -end; +end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Alternative code Einar Heiberg diff --git a/source/mycountunique.m b/source/mycountunique.m index 952e234..5f4e4ae 100644 --- a/source/mycountunique.m +++ b/source/mycountunique.m @@ -13,12 +13,12 @@ if nargin<2 tol = 1e-6; -end; +end if isempty(v) n = 0; return; -end; +end switch class(v) case {'double','single'} @@ -42,9 +42,9 @@ %check if the elements are numeric if nargin>1 warning('Tolerance not used for alphanumeric string.'); - end; + end n = length(unique(v)); otherwise error('Not implemented for other than numeric cells, double, and single.'); -end; +end diff --git a/source/mydel.m b/source/mydel.m index 5de7bbd..beecda0 100644 --- a/source/mydel.m +++ b/source/mydel.m @@ -31,10 +31,10 @@ varargout = cell(1,nargout); if nargout>0 varargout{1} = ok; -end; +end if nargout>1 varargout{2} = message; -end; +end %Alternative code: %if ispc diff --git a/source/mydir.m b/source/mydir.m index 1fc0f5c..721b8e1 100644 --- a/source/mydir.m +++ b/source/mydir.m @@ -11,16 +11,16 @@ if nargin<2 checkfilter = true; -end; +end if checkfilter - try + try %get(DATA.Preview.Handles); This line disabled filter action filter = get(DATA.Preview.Handles.filtercheckbox,'value'); catch %#ok filter = false; - end; -end; + end +end %DATA might not be correctly set => put inside catch clause try @@ -29,14 +29,14 @@ end catch %#ok filter = false; -end; - -if ~filter - f = dir(pathname); %names = ls(pathname); +end + +if ~filter + f = dir(pathname); %names = ls(pathname); else %--- Use filter(s) filtersstri = mygetedit(DATA.Preview.Handles.filteredit); - + %Extract filters numfilters = sum(filtersstri==';')+1; filters = cell(1,numfilters+1); @@ -48,22 +48,22 @@ filters{loop} = filtersstri(1:(pos-1)); filtersstri = filtersstri((pos+1):end); loop = loop+1; - end; + end filters{loop} = filtersstri; - + %Set up template f = []; - + for loop=1:length(filters) f = cat(1,f,dir([pathname filesep filters{loop}])); - end; - - end; + end + +end % names=cellstr(names); % names=strtrim(names); % isd=num2cell(cellfun(@isempty,strfind(names,'.'))); % f=struct('name',names,'isdir',isd); -% +% % % Windows 10(?) bugfix: Sometimes isdir is not set for . and .. for floop = 1:length(f) fname = f(floop).name; @@ -81,32 +81,32 @@ for loop=1:length(f) if isequal(f(loop).name,'thumbs.cache') ind(loop) = false; - end; + end if isequal(f(loop).name,'folders.cache') ind(loop) = false; - end; + end if isequal(f(loop).name,'dicom.cache') ind(loop) = false; - end; + end if isequal(lower(f(loop).name),'dicomdir') ind(loop) = false; - end; - if isequal(f(loop).name,'.svn'), - ind(loop) = false; end - % if strcmp(f(loop).name,'..'), - % ind(loop) = false; + if isequal(f(loop).name,'.svn') + ind(loop) = false; + end + % if strcmp(f(loop).name,'..'), + % ind(loop) = false; %end %if strcmp(f(loop).name,'.'), - %ind(loop) = false; -% %end -% if strcmp(f(loop).name,''), -% ind(loop) = false; -% end -end; + %ind(loop) = false; + % %end + % if strcmp(f(loop).name,''), + % ind(loop) = false; + % end +end % Exclude hidden files on unix, i.e. starting with . but isn't . or .. -if DATA.Pref.HideFilesUnix && isunix +if isunix && isfield(DATA.Pref,'HideFilesUnix')&& DATA.Pref.HideFilesUnix for loop = 1:length(f) if ~isequal(f(loop).name, '.') && ~isequal(f(loop).name, '..') thisname = f(loop).name; diff --git a/source/mydisp.m b/source/mydisp.m index 3dc84a6..c31ef63 100644 --- a/source/mydisp.m +++ b/source/mydisp.m @@ -3,13 +3,13 @@ function mydisp(stri) global DATA stri = translation.dictionary(stri); - +stri = tools('maskpatientstrings',stri); stri = char(textwrap({stri},60)); try if ~DATA.Silent disp(stri); - end; + end catch %#ok disp(stri); -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/mydispexception.p b/source/mydispexception.p index c8870df..b973245 100644 Binary files a/source/mydispexception.p and b/source/mydispexception.p differ diff --git a/source/myexecutableext.m b/source/myexecutableext.m new file mode 100644 index 0000000..22772e1 --- /dev/null +++ b/source/myexecutableext.m @@ -0,0 +1,17 @@ +function s = myexecutableext +%MYEXECUTABLEEXT Returns proper file extension for exectutables. +% +%See also, MYREQUIREPC, MYMKDIR, MYMOVEFILE, MYCOPYFILE, MYDEL, MYDIR. + +%Einar Heiberg + +if ispc + s = '.exe'; +else + temp = mexext; + s = temp(4:end); + s = ['_' s]; + if isequal(s, '_maci64') + s = '_maci'; + end +end \ No newline at end of file diff --git a/source/myfailed.m b/source/myfailed.m index 06ab09c..8b83be6 100644 --- a/source/myfailed.m +++ b/source/myfailed.m @@ -1,4 +1,5 @@ function myfailed(stri,fighandle) +global DATA %MYFAILED(STRI,FIGHANDLE) % Displays an error message STRI. FIGHANDLE is % an optional alignment indicating alignment. @@ -6,6 +7,9 @@ function myfailed(stri,fighandle) % possibility to hit return to okey the message. % Alignment string may be a fig handle or an MYGUI object. % +% If DATA.Silent then message is just displayed in the console +% and exectution continues as if user had pressed ok. +% %See also MYWARNING, MYMSGBOX, MYADJUST, MYWAITBARSTART. %Einar Heiberg @@ -13,7 +17,17 @@ function myfailed(stri,fighandle) if nargin<1 myfailed('Expected one input argument.'); return; -end; +end + +%If silent then just "write to log-file" and return +try + if DATA.Silent + disp(sprintf('Error: %s',stri)); %#ok + return; + end +catch + %Do nothing as if error then depends on DATA not initialised +end stri = translation.dictionary(stri); @@ -26,22 +40,53 @@ function myfailed(stri,fighandle) return end -h = errordlg(stri,translation.dictionary('Operation failed.')); - +h = errordlg(stri,dprintf('Operation failed.'),'invisible'); +try + if ~isempty(DATA) + htext = findobj(h, 'Type', 'Text'); %find text control in dialog + set(htext,'Color',DATA.GUISettings.ForegroundColor,'FontSize',9,'Units','normalized'); + end +catch me + mydispexception(me) +end +setupicon(h); + +try + set(h,'Color',DATA.GUISettings.BackgroundColor); + kids = h.Children; + for i=1:length(kids) + try set(kids(i),'BackgroundColor',DATA.GUISettings.BackgroundColor);catch, end + try set(kids(i),'Color',DATA.GUISettings.BackgroundColor);catch, end + try set(kids(i),'ForegroundColor',DATA.GUISettings.ForegroundColor);catch, end + try + kidstyle = kids(i).Style; + if strcmp(kidstyle,'pushbutton') + set(kids(i),'Units','normalized','FontSize',9) + end + catch + end + end +catch +end +if length(stri) > 40 + ps = get(h,'Position'); + set(h,'Position',[ps(1) ps(2) ps(3)*1.2 ps(4)]) +end try if nargin>1 myadjust(h,fighandle); else myadjust(h); - end; + end catch %#ok -end; +end set(h,'windowstyle','modal'); +set(h,'visible','on'); flushlog; uiwait(h); try macro_helper('put','pushtobuffer(''KeyStroke'',''ok''); %ok from myfailed'); macro_helper('switchorder'); %We need to store data in buffer before the callback catch %#ok -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/mygetcurrentpoint.m b/source/mygetcurrentpoint.m index 914ec77..da8c352 100644 --- a/source/mygetcurrentpoint.m +++ b/source/mygetcurrentpoint.m @@ -16,7 +16,7 @@ y = p(2); else y = p(3); - end; + end else if length(DATA.Buffer.CurrentPoint)<2 p = get(h,'CurrentPoint'); @@ -25,12 +25,12 @@ y = p(2); else y = p(3); - end; + end else x = popfrombuffer('CurrentPoint'); y = popfrombuffer('CurrentPoint'); - end; - end; + end + end catch return; end @@ -40,4 +40,4 @@ namestri = inputname(1); macro_helper('put',sprintf('pushtobuffer(''CurrentPoint'',[%0.5g %0.5g]); %% %s %s',x,y,stri,namestri)); macro_helper('switchorder'); %We need to store data in buffer before the callback -end; \ No newline at end of file +end diff --git a/source/mygetedit.m b/source/mygetedit.m index be5ec34..90b6697 100644 --- a/source/mygetedit.m +++ b/source/mygetedit.m @@ -13,11 +13,11 @@ else stri = popfrombuffer('EditString'); set(h,'String',stri); %Store value - end; -end; + end +end if DATA.RecordMacro tagstri = get(h,'tag'); macro_helper('put',sprintf('pushtobuffer(''EditString'',''%s''); %% %s',stri,tagstri)); macro_helper('switchorder'); %We need to position the slider data before the callback -end; +end diff --git a/source/mygetframe.m b/source/mygetframe.m index 7e794c6..02dd537 100644 --- a/source/mygetframe.m +++ b/source/mygetframe.m @@ -5,6 +5,8 @@ if nargin > 0 h = varargin{1}; + oldunits = get(h,'Units'); + oldposition = get(h,'Position'); set(h,'Units','normalized'); pos = get(h,'Position'); if any(pos(1:2) < 0) || any(pos(1:2)+pos(3:4) > 1) @@ -13,6 +15,10 @@ end try z = getframe(varargin{:}); + if nargin > 0 + set(h,'Units',oldunits); + set(h,'Position',oldposition); + end catch %#ok myfailed('Could not perform screen capture. Could be depending on two monitors. Please move main window to primary monitor and retry.'); -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/mygetlistbox.m b/source/mygetlistbox.m index 93c2930..802756f 100644 --- a/source/mygetlistbox.m +++ b/source/mygetlistbox.m @@ -14,14 +14,14 @@ else v = popfrombuffer('ListboxValue'); set(h,'value',v); %Store the value - end; -end; + end +end if DATA.RecordMacro stri = get(h,'tag'); macro_helper('put',sprintf('pushtobuffer(''ListboxValue'',%0.5g); %% %s',v,stri)); macro_helper('switchorder'); %We need to position the slider data before the callback -end; +end catch %#ok %This catch is to catch when DATA struct is not initialized v = get(h,'value'); diff --git a/source/mygetnumber.m b/source/mygetnumber.m index 8a1b583..d2201e2 100644 --- a/source/mygetnumber.m +++ b/source/mygetnumber.m @@ -16,23 +16,26 @@ if nargin<3 error('Expected at least three input arguments (prompt,title,default).'); -end; +end if nargin==4 error('When minimal value is specified, then also maximal value needs to be specified.'); -end; +end if DATA.Testing testing = DATA.Testing; else testing = false; -end; +end if DATA.RecordMacro recordmacro = DATA.RecordMacro; else recordmacro = false; -end; +end + +promptstri = translation.dictionary(promptstri); +titlestri = translation.dictionary(titlestri); if testing %Take from buffer @@ -41,11 +44,11 @@ ok = true; else error('No number in buffer.'); - end; + end else %Ask user z = []; - s = inputdlg({promptstri},titlestri,1,{sprintf('%0.9g',default)}); + s = myinputdlg({promptstri},titlestri,1,{sprintf('%0.9g',default)}); if isempty(s) ok = false; return; @@ -53,28 +56,28 @@ [z,ok] = str2num(s{1}); %#ok if not(ok) return; - end; + end if length(z)>1 || isempty(z) ok = false; myfailed('Need to be a scalar value.'); return; - end; + end if nargin>3 if zmaxval myfailed(dprintf('Too large value. [%0.5g %0.5g]',minval,maxval)); ok = false; return; - end; - end; - end; -end; + end + end + end +end if recordmacro macro_helper('put',sprintf('pushtobuffer(''Number'',[ %0.9g DATA.Buffer.Number]); %%add to buffer',z)); macro_helper('switchorder'); %We need to store data in buffer before the callback -end; +end diff --git a/source/mygetvalue.m b/source/mygetvalue.m index fe4e9a4..a228b91 100644 --- a/source/mygetvalue.m +++ b/source/mygetvalue.m @@ -13,12 +13,12 @@ else v = popfrombuffer('SliderValue'); set(h,'value',v); %Store value - end; -end; + end +end if DATA.RecordMacro stri = get(h,'tag'); namestri = inputname(1); macro_helper('put',sprintf('pushtobuffer(''SliderValue'',%0.5g); %% %s %s',v,stri,namestri)); macro_helper('switchorder'); %We need to position the slider data before the callback -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/mygui.m b/source/mygui.m index 05f3842..e0d5a83 100644 --- a/source/mygui.m +++ b/source/mygui.m @@ -3,7 +3,7 @@ %G = MYGUI(FIGFILENAME,<'BLOCKING'>); % %The purpose of this class is to facilitate to generate -%GUI's than can also work as a temporary containter data +%GUI's than can also work as a temporary containter data %for that so that data transfer between subfunctions becomes %simple. If blocking is specified then segment internal blocking %figure mechanism will be used. @@ -51,7 +51,7 @@ % %See also SUBSREF, SUBSASGN. -%Jane Sjögren +%Jane Sj?gren classdef mygui < handle %Inherits from handles to get persistent objects. @@ -60,25 +60,28 @@ blocking = false; handles = []; fig = []; - end; + end methods %-------------- function g = mygui(filename,blocking) - + global DATA %Constructor + isinvisble = false; if nargin>1 - if isequal(blocking,'blocking'); + if isequal(blocking,'blocking') blocking = true; + elseif isequal(blocking,'invisible') + isinvisble = true; else error('Expected ''blocking'''); - end; - end; + end + end if nargin<2 blocking = false; - end; + end g.fig = []; %save both as internal class and also as a appdata (later) g.filename = filename; %OK to have here since read only @@ -87,9 +90,15 @@ g.fig = openfig(g.filename,'reuse','invisible'); %set visble off until position is set and handles are stored if g.blocking blockfig(g.fig); - end; + end - set(g.fig,'Color',get(0,'defaultUicontrolBackgroundColor')); + if ~isempty(DATA) + set(g.fig,'Color',DATA.GUISettings.BackgroundColor); %get(0,'defaultUicontrolBackgroundColor')); + else + end + + setupicon(g.fig); %set up Segment icon + %set(g.fig,'renderer','opengl'); %subsasgn(g,'handles',guihandles(g.fig)); %Store handles as application data @@ -99,10 +108,17 @@ setguiposition(g);%set saved position must be set after handles have been set g.handles = guihandles(g.fig); %Store handles as application data %Moved this line down. JS, EH: translation.translatealllabels(g.fig); %Translate labels into preferred language - - set(g.fig,'visible','on');%set visble off until position is set and handles are stored + if not(isempty(DATA)) && ~isempty(DATA.Pref) % if non-existent then the default color is use anyway + setinterfacecolor(g.fig); %set background color and text color for all objects in alla interfaces + end + lgcolor = [0.94 0.94 0.94]; + try set(DATA.Handles.iconuipanel,'BackgroundColor',lgcolor); catch, end + + if ~isinvisble + set(g.fig,'visible','on');%set visble off until position is set and handles are stored + end flushlog; - end; + end %------------------ function display(g) @@ -114,9 +130,9 @@ function display(g) if ~ismember(c{loop},{'GUIDEOptions','lastValidTag','Listeners','SavedVisible'}) type = class(getappdata(g.fig,c{loop})); disp(sprintf(' %s: %s',c{loop},type)); - end; - end; - end; + end + end + end %--------------------------- function g = subsasgn(g,s,v) @@ -140,15 +156,15 @@ function display(g) g.handles = v; else setappdata(g.fig,s.subs,v); - end; + end else error('Invalid syntax, expected ''gui.field = value''.'); - end; + end else %Longer than one more complex interaction if ~isequal(s(1).type,'.') error('Invalid syntax, expected ''gui.field...'''); - end; + end if isequal(s(1).subs,'handles') g = builtin('subsasgn',g,s,v); else @@ -163,13 +179,13 @@ function display(g) temp = []; temp = subsasgn(temp,s(2:end),v); setappdata(g.fig,s(1).subs,temp); %Store it - end; - end; - end; + end + end + end else %STRING setappdata(g.fig,s,v); - end; + end end %----------------------------- @@ -182,7 +198,7 @@ function display(g) %Check if first is . (has to be). if ~isequal(s(1).type,'.') error('Invalid syntax. Valid syntax is gui.name or gui.handles.handle'); - end; + end switch s(1).subs case 'handles' @@ -190,7 +206,7 @@ function display(g) p = subsref(g.handles,s(2:end)); else p = g.handles; - end; + end otherwise if isstruct(s) %struct @@ -201,19 +217,19 @@ function display(g) p = getappdata(g.fig,s.subs); else error('Field ''%s'' does not exist.',s.subs); - end; + end else %Complex temp = getappdata(g.fig,s(1).subs); p = subsref(temp,s(2:end)); - end; + end else %char p = getappdata(g.fig,s); - end; - end; - end; + end + end + end %----------------------------- function g = close(g) @@ -317,7 +333,11 @@ function setguiposition(g) set(g.fig,'units','normalized'); - filename=g.filename; + if isempty(DATA) + return; + end + + filename = g.filename; %search for saved position guipos=[]; @@ -326,8 +346,7 @@ function setguiposition(g) if isequal(DATA.GUIPositions(loop).FileName,filename) guipos=DATA.GUIPositions(loop).Position; end - if isequal(DATA.GUIPositions(loop).FileName,'segment.fig')||... - isequal(DATA.GUIPositions(loop).FileName,['+cvq' filesep 'csegment.fig']) ||... + if isequal(DATA.GUIPositions(loop).FileName,'segment.fig')||... isequal(DATA.GUIPositions(loop).FileName,['+segmentct' filesep 'segmentct.fig']) ||... isequal(DATA.GUIPositions(loop).FileName,['+segmentmr' filesep 'segmentmr.fig']) segmentpos=DATA.GUIPositions(loop).Position; @@ -345,7 +364,6 @@ function setguiposition(g) if guipos(2) > 0.8 || tcypos > 0.8 || guipos(2) < 0.1 || tcypos < 0.1 || ... guipos(1) > 0.9 || tcxpos > 0.9 || guipos(1) < 0.1 || tcxpos < 0.1 if isequal(DATA.GUIPositions(loop).FileName,'segment.fig')||... - isequal(DATA.GUIPositions(loop).FileName,['+cvq' filesep 'csegment.fig']) ||... isequal(DATA.GUIPositions(loop).FileName,['+segmentct' filesep 'segmentct.fig']) ||... isequal(DATA.GUIPositions(loop).FileName,['+segmentmr' filesep 'segmentmr.fig']) guipos = [0.1 0.1 0.8 0.7]; @@ -410,6 +428,6 @@ function setdlgposition(g,h) end - end; %End private methods + end %End private methods end diff --git a/source/myicon.m b/source/myicon.m index 9b6e3b8..5d4f705 100644 --- a/source/myicon.m +++ b/source/myicon.m @@ -3,12 +3,13 @@ %Klas Berggren & Einar Heiberg classdef myicon < handle %Inherits from handles to get persistent objects. - + properties (SetAccess = public) name=''; dropdowniconcell={}; dropdowniconholder=[]; - dropdownaxes=[]; + dropdownpanel = []; %dropdown axes are placed in panels + dropdownaxes=[]; parentobj=[]; mouseovertext=[]; cdata = []; @@ -22,26 +23,26 @@ type=0 group=1; end - + methods function g = myicon(name,parentobj,cdata,text,execute,type,group,cdataIndent,dropdowniconcell)%cdataClicked,cdataDisplay) - + if nargin==1 - text=[]; - end - - if nargin<6 - g.type=1; - else - g.type=type; - end - - if nargin<7 + text=[]; + end + + if nargin<6 + g.type=1; + else + g.type=type; + end + + if nargin<7 g.group=1; - else - g.group=group; - end - + else + g.group=group; + end + %Set properties g.name=name; g.parentobj=parentobj; @@ -56,56 +57,79 @@ g.generateclickeddisabledandindent(cdata,cdataIndent) end + %generate all stuff needed for dropdowniconholders if nargin==9 - g.dropdowniconcell=dropdowniconcell; + g.dropdowniconcell = dropdowniconcell; +% fig = g.parentobj.axeshandle.Parent.Parent; +% p = uipanel('parent',fig,'units','normalized','position',[0 0 1 1],'BorderType','none','Visible','off'); +% ax = axes('parent',p,'units','normalized','position',[0 0 1 1]); +% g.dropdowniconholder = myiconplaceholder(ax); +% add(g.dropdowniconholder,g.dropdowniconcell); +% g.dropdownpanel.Visible = 'off'; +% g.dropdownpanel = p; +% g.dropdownaxes = ax; + +% % % fig = g.parentobj.axeshandle.Parent.Parent; +% % % p = uipanel('parent',fig,'units','normalized','position',[0 0 0 0],'BorderType','none','Visible','off'); +% % % ax = axes('parent',p,'units','normalized','position',[0 0 1 1]); + +% % add(g.dropdowniconholder,g.dropdowniconcell) +% g.dropdownpanel.Visible = 'off'; + end + if g.type ~= 0 && g.type ~= 1 && g.type ~= 2 && g.type ~= 3 + g.enabled = 0; + g.cdataDisplay=g.cdataDisabled; end end + %-------------------------------------------------- function generateclickeddisabledandindent(varargin) - g=varargin{1}; - cdata=varargin{2}; - tmp=cdata; - tmp(cdata==240)=100; - g.cdataClicked=uint8(tmp); - cdataDisabled=rgb2gray(cdata)/5; - cdataDisabled=cdataDisabled+(240-max(max(cdataDisabled)));%(cdataDisabled>240)=240; + g = varargin{1}; + cdata = varargin{2}; + tmp = cdata; + tmp(cdata==240) = 100; + g.cdataClicked = uint8(tmp); + cdataDisabled = rgb2gray(cdata)/5; + cdataDisabled = cdataDisabled+(240-max(max(cdataDisabled)));%(cdataDisabled>240)=240; g.cdataDisabled=uint8(repmat(cdataDisabled,1,1,3)); %Allows user to specify how indented button should look like if nargin<3 tmp=g.cdata; - tmp(g.cdata==240)=160; + tmp(g.cdata==240)=160; g.cdataIndent=uint8(tmp); else g.cdataIndent=varargin{3}; end end - function highlight(varargin) + %--------------------------- + function highlight(varargin) g=varargin{1}; - if g.enabled - g.cdataDisplay=g.cdataClicked; - end + if g.enabled + g.cdataDisplay=g.cdataClicked; end + end - function unhighlight(varargin) - + %----------------------------- + function unhighlight(varargin) + g=varargin{1}; %First check so that button is enabled - if g.enabled - %Check that if the button we are over is the same as the the - %clicked button, if so indent it. If not we want to unhighlight the previous button - currenticon=g.parentobj.geticon; - crit1 = isequal(currenticon,g.parentobj.clickedicon); - crit2 = isequal(hittest(g.parentobj.fig),g.parentobj.imagehandle); - if crit1 && crit2 - switch g.type + if g.enabled + %Check that if the button we are over is the same as the the + %clicked button, if so indent it. If not we want to unhighlight the previous button + currenticon=g.parentobj.geticon; + crit1 = isequal(currenticon,g.parentobj.clickedicon); + crit2 = isequal(hittest(g.parentobj.fig),g.parentobj.imagehandle); + if crit1 && crit2 + switch g.type case 0 %one click button - g.cdataDisplay=g.cdata; + g.cdataDisplay=g.cdata; case 1 %dentstick button - g.cdataDisplay=g.cdataIndent; - g.isindented=1; + g.cdataDisplay=g.cdataIndent; + g.isindented=1; case 2 %toggle button if g.isindented g.cdataDisplay=g.cdata; @@ -114,8 +138,8 @@ function unhighlight(varargin) g.cdataDisplay=g.cdataIndent; g.isindented=1; end - case 3 %dropdown button - if g.isindented + case 3 %dropdown button + if g.isindented g.cdataDisplay=g.cdata; g.isindented=0; else @@ -123,116 +147,168 @@ function unhighlight(varargin) g.isindented=1; end end - %Redundant for most cases but assures that play button gets - %proper appearance - g.parentobj.render - - %Kill timer in parent so we dont display text - if ~isempty(g.parentobj.timer) - g.parentobj.displayinfo=0; - stop(g.parentobj.timer); - delete(g.parentobj.timer); - g.parentobj.timer=[]; - end - if g.type~=3 - feval(g.execute); - else - %g.setdropdown -% if g.isindented -% %do dropdown i.e place new temporary iconaxes which contains -% %a dropdown iconholder -% -% %Number of rows and cols in iconholder divide this with the height and width of -% %the axes of iconholder also calculate lower left corner of -% [iconcornerx,iconcornery] = buttoncorner(g.parentobj,g.name); -% -% rows = size(g.parentobj.iconCell,1); -% cols = size(g.parentobj.iconCell,2); -% pos =plotboxpos(g.parentobj.axeshandle);%get(g.parentobj.axeshandle,'position'); -% iconheight = pos(4)/rows; %in gui -% iconwidth = pos(3)/cols; %in gui -% offsety = size(g.dropdowniconcell,1)*iconheight; -% -% %place new axes on bottom left corner of dropdown icon -% newaxespos = [iconcornerx,iconcornery-offsety,iconwidth,offsety+iconheight/2]; -% fig = get(g.parentobj.axeshandle,'parent'); -% ax = axes('parent',fig,'units','normalized','position',newaxespos); -% g.dropdownaxes=ax; %add to dropdown axes field -% %add iconholder to axes and render -% g.dropdowniconholder = myiconplaceholder(ax,0,3); -% g.parentobj.dropdowniconholders{end+1} = g.dropdowniconholder; -% add(g.dropdowniconholder,g.dropdowniconcell) -% -% for i = 1:numel(g.dropdowniconcell) -% g.dropdowniconcell{i}.parentobj.axeshandle -% end -% -% else -% g.parentobj.dropdowniconholders([g.parentobj.dropdowniconholders{:}]==g.dropdowniconholder)=[]; -% delete(g.dropdownaxes); -% delete(g.dropdowniconholder); -% g.dropdowniconholder = []; -% g.dropdownaxes=[]; -% end - end - else - g.cdataDisplay=g.cdata; - end - end + %Redundant for most cases but assures that play button gets + %proper appearance + g.parentobj.render + + %Kill timer in parent so we dont display text + if ~isempty(g.parentobj.texttimer) + g.parentobj.displayinfo=0; + stop(g.parentobj.texttimer); + delete(g.parentobj.texttimer); + g.parentobj.texttimer=[]; + end + if g.type~=3 + feval(g.execute); + else + %g.setdropdown + % if g.isindented + % %do dropdown i.e place new temporary iconaxes which contains + % %a dropdown iconholder + % + % %Number of rows and cols in iconholder divide this with the height and width of + % %the axes of iconholder also calculate lower left corner of + % [iconcornerx,iconcornery] = buttoncorner(g.parentobj,g.name); + % + % rows = size(g.parentobj.iconCell,1); + % cols = size(g.parentobj.iconCell,2); + % pos =plotboxpos(g.parentobj.axeshandle);%get(g.parentobj.axeshandle,'position'); + % iconheight = pos(4)/rows; %in gui + % iconwidth = pos(3)/cols; %in gui + % offsety = size(g.dropdowniconcell,1)*iconheight; + % + % %place new axes on bottom left corner of dropdown icon + % newaxespos = [iconcornerx,iconcornery-offsety,iconwidth,offsety+iconheight/2]; + % fig = get(g.parentobj.axeshandle,'parent'); + % ax = axes('parent',fig,'units','normalized','position',newaxespos); + % g.dropdownaxes=ax; %add to dropdown axes field + % %add iconholder to axes and render + % g.dropdowniconholder = myiconplaceholder(ax,0,3); + % g.parentobj.dropdowniconholders{end+1} = g.dropdowniconholder; + % add(g.dropdowniconholder,g.dropdowniconcell) + % + % for i = 1:numel(g.dropdowniconcell) + % g.dropdowniconcell{i}.parentobj.axeshandle + % end + % + % else + % g.parentobj.dropdowniconholders([g.parentobj.dropdowniconholders{:}]==g.dropdowniconholder)=[]; + % delete(g.dropdownaxes); + % delete(g.dropdowniconholder); + % g.dropdowniconholder = []; + % g.dropdownaxes=[]; + % end + end + else + g.cdataDisplay=g.cdata; + end + end + end + + %----------------------------- + function showdropdown(varargin) + g = varargin{1}; + if g.isindented + if isequal(g.dropdownpanel.Visible,'off') + %uistack(g.dropdownpanel,'top'); + g.dropdownpanel.Visible = 'on'; + add(g.dropdowniconholder,g.dropdowniconcell) + end + else + if isequal(g.dropdownpanel.Visible,'on') + g.dropdownpanel.Visible = 'off'; + end end + end + + %----------------------------- + function placedropdown(varargin) + g = varargin{1}; + %do dropdown i.e place new temporary iconaxes which contains + %a dropdown iconholder + + %Number of rows and cols in iconholder divide this with the height and width of + %the axes of iconholder also calculate lower left corner of + [iconcornerx,iconcornery] = buttoncorner(g.parentobj,g.name); + + rows = size(g.parentobj.iconCell,1); + cols = size(g.parentobj.iconCell,2); + pos = plotboxpos(g.parentobj.axeshandle);%get(g.parentobj.axeshandle,'position'); + + panelpos = g.parentobj.axeshandle.Parent.Position; + %snap buttoncorner to panelbottom + iconcornery = panelpos(2); + + + iconheight = pos(4)*panelpos(4)/rows; %in gui + iconwidth = pos(3)*panelpos(3)/cols*1.2; %in gui + offsety = (size(g.dropdowniconcell,1))*iconheight-0*iconheight/2; + newaxespos = [iconcornerx,iconcornery-offsety-iconheight/2,iconwidth,offsety+iconheight/2]; + g.dropdownpanel.Position = newaxespos; + + end + - function setdropdown(varargin) - g=varargin{1}; - - if length(varargin)<2 - isindented = g.isindented; - else - isindented = varargin{2}; - end - - if isindented - %do dropdown i.e place new temporary iconaxes which contains - %a dropdown iconholder - - %Number of rows and cols in iconholder divide this with the height and width of - %the axes of iconholder also calculate lower left corner of - [iconcornerx,iconcornery] = buttoncorner(g.parentobj,g.name); - - rows = size(g.parentobj.iconCell,1); - cols = size(g.parentobj.iconCell,2); - pos =plotboxpos(g.parentobj.axeshandle);%get(g.parentobj.axeshandle,'position'); - iconheight = pos(4)/rows; %in gui - iconwidth = pos(3)/cols; %in gui - offsety = size(g.dropdowniconcell,1)*iconheight; - - %place new axes on bottom left corner of dropdown icon - newaxespos = [iconcornerx,iconcornery-offsety,iconwidth,offsety+iconheight/2]; - fig = get(g.parentobj.axeshandle,'parent'); - ax = axes('parent',fig,'units','normalized','position',newaxespos); - g.dropdownaxes=ax; %add to dropdown axes field - %add iconholder to axes and render - g.dropdowniconholder = myiconplaceholder(ax,0,3); - if isempty(g.parentobj.dropdowniconholders) - g.parentobj.dropdowniconholders = g.dropdowniconholder; - else - g.parentobj.dropdowniconholders(end+1) = g.dropdowniconholder; - end - add(g.dropdowniconholder,g.dropdowniconcell) - else - - if ~isempty(g.parentobj.dropdowniconholders) - g.parentobj.dropdowniconholders(g.parentobj.dropdowniconholders==g.dropdowniconholder)=[]; - delete(g.dropdownaxes); - delete(g.dropdowniconholder); - g.dropdowniconholder = []; - g.dropdownaxes=[]; - end - - end - end - function undent(varargin) +% if isindented +% %do dropdown i.e place new temporary iconaxes which contains +% %a dropdown iconholder +% +% %Number of rows and cols in iconholder divide this with the height and width of +% %the axes of iconholder also calculate lower left corner of +% [iconcornerx,iconcornery] = buttoncorner(g.parentobj,g.name); +% +% rows = size(g.parentobj.iconCell,1); +% cols = size(g.parentobj.iconCell,2); +% pos = plotboxpos(g.parentobj.axeshandle);%get(g.parentobj.axeshandle,'position'); +% +% if strcmp(g.parentobj.axeshandle.Parent.Type,'uipanel') +% panelpos = g.parentobj.axeshandle.Parent.Position; +% fig = g.parentobj.axeshandle.Parent.Parent; +% %snap buttoncorner to panelbottom +% iconcornery = panelpos(2); +% else +% panelpos = [0,0,1,1]; +% fig = g.parentobj.axeshandle.Parent; +% end +% +% iconheight = pos(4)*panelpos(4)/rows; %in gui +% iconwidth = pos(3)*panelpos(3)/cols*1.2; %in gui +% offsety = (size(g.dropdowniconcell,1))*iconheight-0*iconheight/2; +% +% %place new axes on bottom left corner of dropdown icon +% newaxespos = [iconcornerx,iconcornery-offsety-iconheight/2,iconwidth,offsety+iconheight/2]; +% p = uipanel('parent',fig,'units','normalized','position',newaxespos,'BorderType','none'); +% ax = axes('parent',p,'units','normalized','position',[0 0 1 1]); +% g.dropdownpanel = p; +% g.dropdownaxes = ax; %add to dropdown axes field +% +% %add iconholder to axes and render +% g.dropdowniconholder = myiconplaceholder(ax,0,3); +% if isempty(g.parentobj.dropdowniconholders) +% g.parentobj.dropdowniconholders = g.dropdowniconholder; +% else +% g.parentobj.dropdowniconholders(end+1) = g.dropdowniconholder; +% end +% add(g.dropdowniconholder,g.dropdowniconcell) +% else +% +% if (~isempty(g.parentobj.dropdowniconholders)) && (~isempty(g.dropdowniconholder)) +% g.parentobj.dropdowniconholders(g.parentobj.dropdowniconholders==g.dropdowniconholder)=[]; +% delete(g.dropdownaxes); +% delete(g.dropdownpanel); +% delete(g.dropdowniconholder); +% g.dropdowniconholder = []; +% g.dropdownpanel = []; +% g.dropdownaxes = []; +% end +% +% end +% end + + %------------------------ + function undent(varargin) g=varargin{1}; g.isindented=0; if g.enabled @@ -240,22 +316,25 @@ function undent(varargin) else g.cdataDisplay=g.cdataDisabled; end - end - - function enable(varargin) + end + + %------------------------ + function enable(varargin) g=varargin{1}; g.enabled=1; g.cdataDisplay=g.cdata; g.parentobj.render - end - - function disable(varargin) + end + + %------------------------- + function disable(varargin) g=varargin{1}; g.enabled=0; g.cdataDisplay=g.cdataDisabled; g.parentobj.render - end + end + %------------------------- function setIcon(varargin) g=varargin{1}; g.cdata=varargin{2}; diff --git a/source/myiconplaceholder.m b/source/myiconplaceholder.m index 149b6e6..0a50a1a 100644 --- a/source/myiconplaceholder.m +++ b/source/myiconplaceholder.m @@ -13,7 +13,7 @@ dropdowniconholders=[]; texthandle=[]; displayinfo=0; - timer=[]; + texttimer=[]; clickedicon=[]; buttonisdown=0; isribbon=0; @@ -22,6 +22,7 @@ killtimer=[]; pull2=[]; fig=[]; + iconarray = zeros(128,128,3,'uint8'); end methods @@ -34,21 +35,21 @@ %Added possibility to design ribbon buttons if nargin == 2 - g.isribbon=isribbon; + g.isribbon = isribbon; end %Set pull 2 always places axes to left = 1 or right = 2 if nargin < 3 - g.pull2=1; + g.pull2 = 1; else - g.pull2 =pull2; + g.pull2 = pull2; end if nargin<4 global DATA - g.fig=DATA.fig; + g.fig = DATA.fig; else - g.fig=fig; + g.fig = fig; end end @@ -63,20 +64,48 @@ function add(varargin) %clear any dropdown if adding new icons to placeholder for iconholder = g.dropdowniconholders - delete(iconholder.axeshandle) - iconholder.axeshandle = NaN; - delete(iconholder); +% if ishandle(iconholder) + delete(iconholder.axeshandle.Parent) + delete(iconholder.axeshandle) + iconholder.axeshandle = NaN; + delete(iconholder); +% end end g.dropdowniconholders=[]; - + %if icons are added to a new placeholder this will be their new parent. for i = 1:g.numberoficons + if not(isempty(icons{i})) icons{i}.parentobj=g; + + %add iconholder to axes and render + if not(isempty(icons{i}.type))&& icons{i}.type == 3 % this is the dropdown type + % if ~ishandle(icons{i}.dropdowniconholder) + p = uipanel('parent',g.fig,'units','normalized','position',[0 0 1 1],'BorderType','none','Visible','off','Clipping','off'); + ax = axes('parent',p,'units','normalized','position',[0 0 1 1],'Clipping','off'); + icons{i}.dropdownpanel = p; + icons{i}.dropdownaxes = ax; + icons{i}.dropdowniconholder = myiconplaceholder(ax,0,3); + add(icons{i}.dropdowniconholder,icons{i}.dropdowniconcell) + % end + + if isempty(g.dropdowniconholders) + g.dropdowniconholders = icons{i}.dropdowniconholder; + else + g.dropdowniconholders(end+1) = icons{i}.dropdowniconholder; + end + end + end + end %Adjust axis - axis(g.axeshandle,'image','off'); - axis(g.axeshandle,'ij') - set(g.axeshandle,'DataAspectRatio',[1,1,1]); +% axis(g.axeshandle,'image','off'); +% axis(g.axeshandle,'ij') + set(g.axeshandle,'DataAspectRatio',[1,1,1],'fontsmoothing','off','Clipping','off'); +% set(g.axeshandle,); +% set(g.axeshandle,); + %set(g.axeshandle,'graphicssmoothing','off'); + if iscell(icons) %try to add entire cell position is linear indices @@ -112,20 +141,24 @@ function enable(varargin) end function disable(varargin) - g=varargin{1}; + g = varargin{1}; if nargin==1 for i=1:g.numberoficons g.iconCell{i}.enabled=0; - g.iconCell{i}.cdataDisplay=g.iconCell{i}.cdataDisabled; + if not(strcmp(g.iconCell{i}.name,'verticallinewide')) && not(strcmp(g.iconCell{i}.name,'verticalline')) + g.iconCell{i}.cdataDisplay = g.iconCell{i}.cdataDisabled; + end end else - names=varargin{2}; + names = varargin{2}; for i=1:g.numberoficons if any(strcmp(g.iconCell{i}.name,names)) %g.iconCell{i}.disable g.iconCell{i}.enabled=0; - g.iconCell{i}.cdataDisplay=g.iconCell{i}.cdataDisabled; + if not(strcmp(g.iconCell{i}.name,'verticallinewide')) && not(strcmp(g.iconCell{i}.name,'verticalline')) + g.iconCell{i}.cdataDisplay = g.iconCell{i}.cdataDisabled; + end end end end @@ -133,21 +166,58 @@ function disable(varargin) end function render(varargin) - g=varargin{1}; - cdataCell=cell(size(g.iconCell)); - for i =1:g.numberoficons - icon=g.iconCell{i}; - cdataCell{i}=icon.cdataDisplay; - end - cdata=cell2mat(cdataCell); + g = varargin{1}; + cdataCell = cell(size(g.iconCell)); + for i =1:g.numberoficons + icon = g.iconCell{i}; + cdataCell{i} = icon.cdataDisplay; + end + numrows = size(cdataCell,1); + numcols = size(cdataCell,2); + if numrows > 1 && numcols > 1 + % find maximum length of an icon in the column + maxlencol = zeros(1,numcols); + for col = 1:numcols + for row = 1:numrows + maxlencol(1,col) = max(maxlencol(1,col),size(cdataCell{row,col},2)); + end + end + for col = 1:numcols + for row = 1:numrows + maxlencol = max(maxlencol,size(cdataCell{row,col},2)); + actysize = size(cdataCell{row,col},2); + if actysize < maxlencol(col) && actysize ~= 14 + % padding with zeros + cdataCell{row,col} = padarray(cdataCell{row,col},[0,maxlencol(col)-actysize],240,'post'); + end + end + end +% tempdata = cell(numrows,1); +% maxysize = 0; +% for row = 1:numrows +% tempdata{row,1} = cell2mat(cdataCell(row,:)); +% maxysize = max(maxysize,size(tempdata{row,1},2)); +% end +% for row = 1:numrows +% actysize = size(tempdata{row,1},2); +% if actysize < maxysize +% % padding with zeros +% tempdata{row,1} = padarray(tempdata{row,1},[0,maxysize-actysize],240,'post'); +% end +% end + cdata = cell2mat(cdataCell); + else + cdata = cell2mat(cdataCell); + end + %idea 2 %get axes height then interpolate so that rows= axes height and %length is interpolated so that we have the same aspect ratio. set(g.axeshandle,'Units','pixels'); axpos = get(g.axeshandle,'Position'); - height=axpos(4); - cdata=imresize(cdata,height/size(cdata,1));%imresize(cdata,height/size(cdata,1));%[height,height*g.numberoficons,3]); + height = axpos(4); + cdata = imresize(cdata,height/size(cdata,1));%imresize(cdata,height/size(cdata,1));%[height,height*g.numberoficons,3]); %Here we add a line that fills out the remaining right part of the %axes if we are dealing with a ribbon interface @@ -177,12 +247,13 @@ function render(varargin) %graphics if ~ishandle(g.imagehandle) - g.imagehandle = image(g.cdata,'parent',g.axeshandle); %If handle lost or not yet created recreate it and the texthandle + g.imagehandle = imagesc(g.cdata,'parent',g.axeshandle); %If handle lost or not yet created recreate it and the texthandle + axis(g.axeshandle,'image','off'); %tooltip handle if g.pull2==2 - g.texthandle=text(1,1,'','Parent',g.axeshandle,'Background','white','VerticalAlignment','baseline','HorizontalAlignment','Right','HitTest','off'); + g.texthandle=text(1,1,'','Parent',g.axeshandle,'Background','white','VerticalAlignment','bottom','HorizontalAlignment','Right','HitTest','off'); else - g.texthandle=text(1,1,'','Parent',g.axeshandle,'Background','white','VerticalAlignment','baseline','HorizontalAlignment','Left','HitTest','off'); + g.texthandle=text(1,1,'','Parent',g.axeshandle,'Background','white','VerticalAlignment','bottom','HorizontalAlignment','Left','HitTest','off'); end set(g.texthandle,'visible','off') else @@ -190,8 +261,8 @@ function render(varargin) end %switch that renders images. - axis(g.axeshandle,'image','on'); - axis(g.axeshandle,'image','off'); +% axis(g.axeshandle,'image','on'); +% axis(g.axeshandle,'image','off'); %Assert position oficon placeholders. switch g.pull2 @@ -210,20 +281,21 @@ function render(varargin) %if any dropdown iconholders there adjust their position for i = 1:numel(g.iconCell) - if g.iconCell{i}.type==3 && g.iconCell{i}.isindented %this is the dropdown type + if g.iconCell{i}.type==3 %&& g.iconCell{i}.isindented %this is the dropdown type %The below procedure reboots the dropdowns - g.iconCell{i}.setdropdown(0) - g.iconCell{i}.setdropdown(1) - elseif g.iconCell{i}.type==3 && ~g.iconCell{i}.isindented && ~isempty(g.iconCell{i}.dropdownaxes) - g.iconCell{i}.setdropdown(0) + g.iconCell{i}.placedropdown%(0) + g.iconCell{i}.showdropdown + %g.iconCell{i}.setdropdown(1) + %elseif g.iconCell{i}.type==3 && ~g.iconCell{i}.isindented && ~isempty(g.iconCell{i}.dropdownaxes) + %g.iconCell{i}.setdropdown(0) end end - if ~isempty(g.timer) + if ~isempty(g.texttimer) g.displayinfo=0; - stop(g.timer); - delete(g.timer); - g.timer=[]; + stop(g.texttimer); + delete(g.texttimer); + g.texttimer=[]; end end @@ -245,54 +317,54 @@ function render(varargin) iconsandstates(all(emptyCells,2),:) = []; end - function overicon=geticon(varargin) - g=varargin{1}; + function overicon = geticon(varargin) + g = varargin{1}; try - %find which icon we are over then return it. - clicked=get(g.axeshandle, 'CurrentPoint'); - x_over=clicked(1,1); - y_over=clicked(1,2); - [rows,cols]=size(g.iconCell); - - %No longer true as we rescale the image constantly - %[yres,xres,~] = size(g.iconCell{1}.cdata); - yres = size(g.cdata,1); - xres = size(g.cdata,2); - %xres = size(g.cdata,2)/g.numberoficons;%Not true cant handle variable size buttons - - %get normalized length of icons in iconcell inorder to set up xres - totXsize=0; - totYsize=0; - for i=1:cols - totXsize=totXsize+size(g.iconCell{1,i}.cdata,2); - end - - for i=1:rows - totYsize=totYsize+size(g.iconCell{i,1}.cdata,1); - end - - X_norm=zeros(size(g.iconCell)); - Y_norm=zeros(size(g.iconCell)); - - - for i=1:numel(g.iconCell) - X_norm(i)=size(g.iconCell{i}.cdata,2)/totXsize; - Y_norm(i)=size(g.iconCell{i}.cdata,1)/totYsize; - end - - X_norm=reshape(cumsum(X_norm,2),1,numel(g.iconCell)); - Y_norm=reshape(cumsum(Y_norm,1),1,numel(g.iconCell)); - - %X=0:xres:xres*cols; - X=[0,X_norm.*xres]; - Y=[0,Y_norm.*yres]; - %Y=0:yres:yres*rows; - x_ind=find(x_over>X,1,'last'); - y_ind=find(y_over>Y,1,'last'); - %x_ind=find(x_over>=X,1,'last'); - %y_ind=find(y_over>=Y,1,'last'); - overicon=g.iconCell{y_ind,x_ind}; - catch + %find which icon we are over then return it. + clicked = get(g.axeshandle, 'CurrentPoint'); + x_over = clicked(1,1); + y_over = clicked(1,2); + [rows,cols] = size(g.iconCell); + + %No longer true as we rescale the image constantly + %[yres,xres,~] = size(g.iconCell{1}.cdata); + yres = size(g.cdata,1); + xres = size(g.cdata,2); + %xres = size(g.cdata,2)/g.numberoficons;%Not true cant handle variable size buttons + + %get normalized length of icons in iconcell inorder to set up xres + totXsize = 0; + totYsize = 0; + for i=1:cols + totXsize = totXsize+size(g.iconCell{1,i}.cdata,2); + end + + for i = 1:rows + totYsize = totYsize + size(g.iconCell{i,1}.cdata,1); + end + + X_norm = zeros(size(g.iconCell)); + Y_norm = zeros(size(g.iconCell)); + + for i = 1:numel(g.iconCell) + X_norm(i) = size(g.iconCell{i}.cdata,2)/totXsize; + Y_norm(i) = size(g.iconCell{i}.cdata,1)/totYsize; + end + + if rows > 1 && cols >1 + X_norm = reshape(cumsum(X_norm(1,:),2),1,cols); + Y_norm = reshape(cumsum(Y_norm(:,1),1),1,rows); + else + X_norm = reshape(cumsum(X_norm,2),1,numel(g.iconCell)); + Y_norm = reshape(cumsum(Y_norm,1),1,numel(g.iconCell)); + end + X = [0,X_norm.*xres]; + Y = [0,Y_norm.*yres]; + + x_ind = find(x_over>X,1,'last'); + y_ind = find(y_over>Y,1,'last'); + overicon = g.iconCell{y_ind,x_ind}; + catch %there is a possibility that when we query for location in this %function we nolonger are over a icon overicon=[]; @@ -324,16 +396,36 @@ function undent(varargin) function indent(varargin) - g=varargin{1}; - name=varargin{2}; - runicon=varargin{3}; + g = varargin{1}; + name = varargin{2}; + runicon = varargin{3}; icon=[]; - for i=1:numel(g.iconCell) - if strcmp(g.iconCell{i}.name,name) - icon=g.iconCell{i}; - break; - end + %all the iconholders including dropdowniconholders + iconholders = [g,g.dropdowniconholders]; + + %extract the iconCells from the above iconholders then do name check + shouldskip = false; + parenticonname = []; + for ich = 1:numel(iconholders) + g = iconholders(1,ich); + for i=1:numel(g.iconCell) + if strcmp(g.iconCell{i}.name,name) + icon = g.iconCell{i}; + if ich > 1 + % index larger than 1 indicates that the icon is a dropdown + % find tha corresponding index of parent icon + parentind = cellfun(@(x) isequal(x.dropdowniconholder, icon.parentobj), iconholders(1,1).iconCell); + parenticonname = iconholders(1,1).iconCell{parentind}.name; + end + shouldskip = true; + break; + end + end + if shouldskip + break;% go further as sson as the name was found + end end + if isempty(icon) return; @@ -346,35 +438,57 @@ function indent(varargin) g.iconCell{i}.isindented=0; end end + if ~isempty(parenticonname) + iconholders(1,1).indent(parenticonname,1) + end end - icon.cdataDisplay=icon.cdataIndent; - icon.isindented=1; + + +% if contains(icon.name, 'ribbon3dp') +% iconcells = g.iconCell; +% % Jelena quick fix for highlight both buttons for 3DP Model +% iconcells{end,1}.cdataDisplay = iconcells{end,1}.cdataIndent; +% iconcells{end,1}.isindented = 1; +% iconcells{end,2}.cdataDisplay = iconcells{end,2}.cdataIndent; +% iconcells{end,2}.isindented = 1; +% else + icon.cdataDisplay=icon.cdataIndent; + icon.isindented=1; +% end g.render; if runicon - feval(icon.execute) + feval(icon.execute); end end function click(varargin) - g=varargin{1}; - g.buttonisdown=1; - + g = varargin{1}; + g.buttonisdown = 1; %Save the current click configuration if slide off icon axes - g.configatclick=g.findindented; + g.configatclick = g.findindented; if isequal(hittest(g.fig),g.imagehandle) set(g.fig,'WindowButtonUpFcn',@g.upclick); - g.clickedicon=g.geticon; + g.clickedicon = g.geticon; if ~isempty(g.clickedicon) - g.clickedicon.highlight - set(g.texthandle,'visible','off') - g.displayinfo=0; - if ~isempty(g.timer) - stop(g.timer); - delete(g.timer); - g.timer=[]; - end - g.render + iconcells = g.clickedicon.parentobj.iconCell; +% if contains(g.clickedicon.name, 'ribbon3dp') +% % Jelena quick fix for highlight both buttons for 3DP Model +% iconcells{end,1}.cdataDisplay = iconcells{end,1}.cdataClicked; +% iconcells{end,2}.cdataDisplay = iconcells{end,2}.cdataClicked; +% end + if ~contains(g.clickedicon.name, 'verticalline') + g.clickedicon.highlight + end + + set(g.texthandle,'visible','off') + g.displayinfo=0; + if ~isempty(g.texttimer) + stop(g.texttimer); + delete(g.texttimer); + g.texttimer=[]; + end + g.render %pause(0.1) %inorder to trigger text again %g.motion; @@ -409,7 +523,16 @@ function click(varargin) function [x,y]=buttoncorner(varargin) g=varargin{1}; name=varargin{2}; - pos =plotboxpos(g.axeshandle);%get(g.axeshandle,'position'); + pos =plotboxpos(g.axeshandle);% + %pos = get(g.axeshandle,'position'); + + if strcmp(g.axeshandle.Parent.Type,'figure') + panelpos = ones(1,4); + panelpos(1:2)=0; + else + panelpos = g.axeshandle.Parent.Position; + end + cdataCell=cell(size(g.iconCell)); for i =1:g.numberoficons cdataCell{i}=g.iconCell{i}.cdataDisplay; @@ -433,18 +556,19 @@ function click(varargin) %normalized coordinate system wp= sz(2); - wn=pos(3); + wn=pos(3)*panelpos(3); hp= sz(1); - hn=pos(4); - x = pos(1)+x(col)/wp*wn; - y = pos(2)+y(row)/hp*hn; + hn=pos(4)*panelpos(4); + x = pos(1)+panelpos(1)+x(col)/wp*wn; + y = pos(2)+panelpos(2)+y(row)/hp*hn; end function upclick(varargin) %global DATA - g=varargin{1}; + g = varargin{1}; + % fig=get(g.axeshandle,'parent'); g.buttonisdown=0; @@ -454,11 +578,27 @@ function upclick(varargin) if ~isempty(g.clickedicon) && g.iconCell{k}.group==g.clickedicon.group && g.iconCell{k}.type==1 && g.clickedicon.type==1 g.iconCell{k}.undent; end - end + end + iconcells = g.clickedicon.parentobj.iconCell; +% if contains(g.clickedicon.name, 'ribbon3dp') +% % Jelena quick fix for highlight both buttons for 3DP Model +% iconcells{end,1}.cdataDisplay = iconcells{end,1}.cdataIndent; +% iconcells{end,1}.isindented = 1; +% iconcells{end,2}.cdataDisplay = iconcells{end,2}.cdataIndent; +% iconcells{end,2}.isindented = 1; +% end g.clickedicon.unhighlight else g.notover; end + + %if any dropdown iconholders there show them + for i = 1:numel(g.iconCell) + if g.iconCell{i}.type==3 %&& g.iconCell{i}.isindented %this is the dropdown type + g.iconCell{i}.showdropdown%(0) + end + end + end function motion(varargin) @@ -480,22 +620,40 @@ function motion(varargin) g.notover end - %Start timer so that text doesnt display immediately - if isempty(g.timer) && ~g.displayinfo - g.timer=timer('ExecutionMode','singleShot',... + %Start texttimer so that text doesnt display immediately + if isempty(g.texttimer) && ~g.displayinfo + g.texttimer=timer('ExecutionMode','singleShot',... 'TimerFcn',@g.displayinfoYN, ... 'StartDelay',1); - start(g.timer); + start(g.texttimer); end - %if timer has triggered and we are over the toolbar show text +% %if timer has triggered and we are over the toolbar show text if g.displayinfo - set(g.texthandle,'visible','on') - xy = get(g.axeshandle, 'CurrentPoint'); - x=xy(1,1); - y=xy(1,2); - overicon=g.geticon; - set(g.texthandle,'Position',[x,y,0],'String',translation.dictionary(overicon.mouseovertext));%text(x,y,'blablabla','Parent',g.axeshandle); + + xy = get(g.axeshandle, 'CurrentPoint'); + x=xy(1,1); + y=xy(1,2); + + xl = xlim(g.axeshandle); + yl = ylim(g.axeshandle); + + if y/yl(2)<0.4 + verticalalignment = 'top'; + else + verticalalignment = 'bottom'; + end + + if g.pull2==2 || x/xl(2)>0.8%pull2 + horizontalalignment = 'right'; + offset = -10; + else + horizontalalignment = 'left'; + offset = 10; + end + set(g.texthandle,'Position',[x+offset,y,0],'String',sprintf(translation.dictionary(current_icon.mouseovertext)),... + 'verticalalignment',verticalalignment,'horizontalalignment',... + horizontalalignment,'Clipping','off','Interpreter','none');%text(x,y,'blablabla','Parent',g.axeshandle); end else g.notover @@ -514,10 +672,10 @@ function killtext(varargin) %if we no longer are over the toolbar, kill timer. set(g.texthandle,'visible','off') g.displayinfo=0; - if ~isempty(g.timer) - stop(g.timer) - delete(g.timer) - g.timer=[]; + if ~isempty(g.texttimer) + stop(g.texttimer) + delete(g.texttimer) + g.texttimer=[]; %remove killtimer also stop(g.killtimer) @@ -537,109 +695,6 @@ function killtext(varargin) end - % function notover(varargin) -% global DATA -% g=varargin{1}; -% -% if ~isempty(g.clickedicon) && g.buttonisdown -% g.clickedicon.unhighlight; -% g.clickedicon=[]; -% g.render -% end -% -% %if a user clicks and holds and drags of the iconholder and no button -% %is clicked we clear all indentations and remove buttonupfcn. -% if isempty(g.clickedicon) && ~isempty(g.findindented) && g.buttonisdown -% if g.axeshandle==DATA.Handles.configiconholder.axeshandle; -% for i=1:g.findindented -% -% %undent all but current tool -% if g.iconCell{i}.type==1 && ~strcmp(DATA.CurrentTool,g.iconCell{i}.name) -% g.iconCell{i}.undent; -% else -% g.iconCell{i}.isindented=1; -% g.iconCell{i}.cdataDisplay=g.iconCell{i}.cdataIndent; -% end -% end -% else -% %First the panel group is found -% str=sprintf('%d%d',DATA.ViewMatrix(1),DATA.ViewMatrix(2)); -% switch str -% case '11' -% name='panel1'; -% case '12' -% name='panel2'; -% case '21' -% name='panel2x1'; -% case '13' -% name='panel3'; -% case '31' -% name='panel3x1'; -% case '22' -% name='panel4'; -% case '23' -% name='panel6'; -% end -% -% iconcell=g.iconCell; -% for i= 1:g.numberoficons -% if strcmp(iconcell{i}.name,name) -% ind=i; -% end -% end -% -% iconcell{ind}.cdataDisplay=iconcell{ind}.cdataIndent; -% iconcell{ind}.isindented=1; -% -% %Then view mode -% switch DATA.ViewPanelsType{DATA.CurrentPanel} -% case 'montage' -% name='viewall'; -% case 'one' -% name='viewone'; -% end -% -% for i= 1:g.numberoficons -% if strcmp(iconcell{i}.name,name) -% ind=i; -% end -% end -% -% iconcell{ind}.cdataDisplay=iconcell{ind}.cdataIndent; -% iconcell{ind}.isindented=1; -% end -% -% set(DATA.fig,'WindowButtonUpFcn',[]); -% g.render -% end -% -% %if we no longer are over the toolbar, kill timer. -% set(g.texthandle,'visible','off') -% g.displayinfo=0; -% if ~isempty(g.timer) -% stop(g.timer) -% delete(g.timer) -% g.timer=[]; -% end -% end -% -% function displayinfoYN(varargin) -% %Should we display info now that timer has triggered -% global DATA -% g=varargin{1}; -% if isequal(hittest(DATA.fig),g.imagehandle) && ~g.buttonisdown && ~g.isribbon -% g.displayinfo=1; -% set(g.texthandle,'visible','on') -% overicon=g.geticon; -% xy = get(g.axeshandle, 'CurrentPoint'); -% x=xy(1,1); -% y=xy(1,2); -% set(g.texthandle,'Position',[x,y,0],'String',overicon.mouseovertext);%text(x,y,'blablabla','Parent',g.axeshandle); -% else -% g.displayinfo=0; -% end -% end -% function notover(varargin) % DATA g=varargin{1}; @@ -657,20 +712,20 @@ function notover(varargin) %if we no longer are over the toolbar, kill timer. set(g.texthandle,'visible','off') g.displayinfo=0; - if ~isempty(g.timer) - stop(g.timer) - delete(g.timer) - g.timer=[]; + if ~isempty(g.texttimer) + stop(g.texttimer) + delete(g.texttimer) + g.texttimer=[]; end end function textoff(g) set(g.texthandle,'visible','off') g.displayinfo=0; - if ~isempty(g.timer) - stop(g.timer) - delete(g.timer) - g.timer=[]; + if ~isempty(g.texttimer) + stop(g.texttimer) + delete(g.texttimer) + g.texttimer=[]; end end @@ -683,10 +738,45 @@ function displayinfoYN(varargin) set(g.texthandle,'visible','on') overicon=g.geticon; xy = get(g.axeshandle, 'CurrentPoint'); +% %we need to place the the text better as it is in the way of +% %clicking try adding a small offset also added so that it +% switches direction in the last 20 % of axes. x=xy(1,1); y=xy(1,2); - set(g.texthandle,'Position',[x,y,0],'String',translation.dictionary(overicon.mouseovertext));%text(x,y,'blablabla','Parent',g.axeshandle); + + xl = xlim(g.axeshandle); + yl = ylim(g.axeshandle); + + if y/yl(2)<0.4 + verticalalignment = 'top'; + else + verticalalignment = 'bottom'; + end + + + if g.pull2==2 || x/xl(2)>0.8%pull2 + horizontalalignment = 'right'; + offset = -10; + else + horizontalalignment = 'left'; + offset = 10; + end + set(g.texthandle,'Position',[x+offset,y,0],'String',translation.dictionary(overicon.mouseovertext),'verticalalignment',verticalalignment,'horizontalalignment',horizontalalignment);%text(x,y,'blablabla','Parent',g.axeshandle); uistack(g.axeshandle,'top') +% ht = text(0,0,'*text', 'tag', 'rollover'); +% pointerBehavior.enterFcn = ... +% @(hfig, currentPoint)set(findobj(hfig, 'tag', 'rollover'), ... +% 'string', 'text - here''s some more info...'); +% pointerBehavior.traverseFcn = []; +% % The exitFcn is similar to the enterFcn, but it changes the string back to +% % the shorter version... +% pointerBehavior.exitFcn = ... +% @(hfig, currentPoint)set(findobj(hfig, 'tag', 'rollover'), ... +% 'string', 'text*'); +% % Now, I need to link the pointer behavior to the object (the text box): +% iptSetPointerBehavior(ht, pointerBehavior); +% % Now, I need to enable pointer management for the figure: +% iptPointerManager(gcf, 'enable'); %Start kill text timer that checks for a while if we are over the axis if not kill text %if isempty(g.killtimer) @@ -702,11 +792,25 @@ function displayinfoYN(varargin) function kill(varargin) g = varargin{1}; - if ~isempty(dropdowniconholders) - delete(dropdowniconholders) + if ~isempty(g.dropdowniconholders) + delete(g.dropdowniconholders) end delete(g) end + + function hidedropdown(g) + for loop = 1:length(g.iconCell) + if ~isempty(g.iconCell{loop}.dropdownpanel) + try + g.iconCell{loop}.dropdownpanel.Visible = 'off'; + catch + end + %g.iconCell{loop}.isindented = 0; + %g.iconCell{loop}.undent; + end + end + end + end end \ No newline at end of file diff --git a/source/myinputdlg.m b/source/myinputdlg.m new file mode 100644 index 0000000..db5eacb --- /dev/null +++ b/source/myinputdlg.m @@ -0,0 +1,617 @@ +function Answer = myinputdlg(Prompt, Title, NumLines, DefAns, Resize,HidedPrompt) +%own version of Matlab inputdlg for setting color in figure +% Input dialog box. + +global DATA + +% Nargin Check +narginchk(0,6); +nargoutchk(0,1); + + +if nargin > 0 + Prompt = convertStringsToChars(Prompt); +end + +if nargin > 1 + Title = convertStringsToChars(Title); +end + + +if nargin > 3 + if isstring(DefAns) + DefAns = cellstr(DefAns); + end +end + +if nargin > 4 + Resize = convertStringsToChars(Resize); +end + +if nargin > 5 + isHided = contains(Prompt, HidedPrompt); +end + +% Handle Input Args +if nargin<1 + Prompt=getString(message('MATLAB:uistring:popupdialogs:InputDlgInput')); +end +if ~iscell(Prompt) + Prompt={Prompt}; +end +NumQuest=numel(Prompt); + + +if nargin<2 + Title=' '; +end + +if nargin<3 + NumLines=1; +end + +if nargin<4 + DefAns=cell(NumQuest,1); + for lp=1:NumQuest + DefAns{lp}=''; + end +end + +if nargin<5 + Resize = 'off'; +end +if nargin < 6 + isHided = zeros(size(Prompt)); +end +WindowStyle='modal'; +Interpreter='none'; + +for ExtLp=1:NumQuest + tempPrompt{ExtLp} = translation.dictionary(Prompt{ExtLp}); +end +Prompt = tempPrompt; +Title = translation.dictionary(Title); + +Options = struct([]); %#ok +if nargin==5 && isstruct(Resize) + Options = Resize; + Resize = 'off'; + if isfield(Options,'Resize'), Resize=Options.Resize; end + if isfield(Options,'WindowStyle'), WindowStyle=Options.WindowStyle; end + if isfield(Options,'Interpreter'), Interpreter=Options.Interpreter; end +end + +[rw,cl]=size(NumLines); +OneVect = ones(NumQuest,1); +if (rw == 1 & cl == 2) %#ok Handle [] + NumLines=NumLines(OneVect,:); +elseif (rw == 1 & cl == 1) %#ok + NumLines=NumLines(OneVect); +elseif (rw == 1 & cl == NumQuest) %#ok + NumLines = NumLines'; +elseif (rw ~= NumQuest | cl > 2) %#ok + error(message('MATLAB:inputdlg:IncorrectSize')) +end + +if ~iscell(DefAns) + error(message('MATLAB:inputdlg:InvalidDefaultAnswer')); +end + +%%%%%%%%%%%%%%%%%%%%%%% +%%% Create InputFig %%% +%%%%%%%%%%%%%%%%%%%%%%% +FigWidth=175; +FigHeight=100; +FigPos(3:4)=[FigWidth FigHeight]; %#ok +try FigColor=DATA.GUISettings.BackgroundColor; +catch, FigColor=get(0,'DefaultUicontrolBackgroundColor'); end +try TextColor=DATA.GUISettings.ForegroundColor; +catch, TextColor=get(0,'FactoryUicontrolForegroundColor'); end + +InputFig=dialog( ... + 'Visible' ,'off' , ... + 'KeyPressFcn' ,@doFigureKeyPress, ... + 'Name' ,Title , ... + 'Pointer' ,'arrow' , ... + 'Units' ,'pixels' , ... + 'UserData' ,'Cancel' , ... + 'Tag' ,Title , ... + 'HandleVisibility' ,'callback' , ... + 'Color' ,FigColor , ... + 'NextPlot' ,'add' , ... + 'WindowStyle' ,WindowStyle, ... + 'Resize' ,Resize ... + ); + +%%%%%%%%%%%%%%%%%%%%% +%%% Set Positions %%% +%%%%%%%%%%%%%%%%%%%%% +DefOffset = 5; +DefBtnWidth = 53; +DefBtnHeight = 23; + +TextInfo.Units = 'pixels' ; +TextInfo.FontSize = round(1.2*get(0,'FactoryUicontrolFontSize')); +TextInfo.FontWeight = get(InputFig,'DefaultTextFontWeight'); +TextInfo.HorizontalAlignment= 'left' ; +TextInfo.HandleVisibility = 'callback' ; + +StInfo=TextInfo; +StInfo.Style = 'text' ; +StInfo.BackgroundColor = FigColor; + + +EdInfo=StInfo; +EdInfo.FontWeight = get(InputFig,'DefaultUicontrolFontWeight'); +EdInfo.Style = 'edit'; +EdInfo.BackgroundColor = 'white'; + +BtnInfo=StInfo; +BtnInfo.FontWeight = get(InputFig,'DefaultUicontrolFontWeight'); +BtnInfo.Style = 'pushbutton'; +BtnInfo.HorizontalAlignment = 'center'; +BtnInfo.ForegroundColor = TextColor; + +% Add VerticalAlignment here as it is not applicable to the above. +TextInfo.VerticalAlignment = 'bottom'; +TextInfo.Color = TextColor; + +% adjust button height and width +btnMargin=1.4; +ExtControl=uicontrol(InputFig ,BtnInfo , ... + 'String' ,getString(message('MATLAB:uistring:popupdialogs:Cancel')) , ... + 'Visible' ,'off' ... + ); + +% BtnYOffset = DefOffset; +BtnExtent = get(ExtControl,'Extent'); +BtnWidth = max(DefBtnWidth,BtnExtent(3)+8); +BtnHeight = max(DefBtnHeight,BtnExtent(4)*btnMargin); +delete(ExtControl); + +% Determine # of lines for all Prompts +TxtWidth=FigWidth-2*DefOffset; +ExtControl=uicontrol(InputFig ,StInfo , ... + 'String' ,'' , ... + 'Position' ,[ DefOffset DefOffset 0.96*TxtWidth BtnHeight ] , ... + 'Visible' ,'off' ... + ); + +WrapQuest=cell(NumQuest,1); +QuestPos=zeros(NumQuest,4); + +for ExtLp=1:NumQuest + if size(NumLines,2)==2 + [WrapQuest{ExtLp},QuestPos(ExtLp,1:4)]= ... + textwrap(ExtControl,Prompt(ExtLp),NumLines(ExtLp,2)); + else + [WrapQuest{ExtLp},QuestPos(ExtLp,1:4)]= ... + textwrap(ExtControl,Prompt(ExtLp),80); + end +end % for ExtLp + +delete(ExtControl); +QuestWidth =QuestPos(:,3); +QuestHeight=QuestPos(:,4); +if ismac % Change Edit box height to avoid clipping on mac. + editBoxHeightScalingFactor = 1.4; +else + editBoxHeightScalingFactor = 1; +end +TxtHeight=QuestHeight(1)/size(WrapQuest{1,1},1) * editBoxHeightScalingFactor; +EditHeight=TxtHeight*NumLines(:,1); +EditHeight(NumLines(:,1)==1)=EditHeight(NumLines(:,1)==1)+4; + +FigHeight=(NumQuest+2)*DefOffset + ... + BtnHeight+sum(EditHeight) + ... + sum(QuestHeight); + +TxtXOffset=DefOffset; + +QuestYOffset=zeros(NumQuest,1); +EditYOffset=zeros(NumQuest,1); +QuestYOffset(1)=FigHeight-DefOffset-QuestHeight(1); +EditYOffset(1)=QuestYOffset(1)-EditHeight(1); + +for YOffLp=2:NumQuest + QuestYOffset(YOffLp)=EditYOffset(YOffLp-1)-QuestHeight(YOffLp)-DefOffset; + EditYOffset(YOffLp)=QuestYOffset(YOffLp)-EditHeight(YOffLp); +end % for YOffLp + +QuestHandle=[]; +EditHandle=[]; + +AxesHandle=axes('Parent',InputFig,'Position',[0 0 1 1],'Visible','off'); + +inputWidthSpecified = false; + +for lp=1:NumQuest + if ~ischar(DefAns{lp}) + delete(InputFig); + error(message('MATLAB:inputdlg:InvalidInput')); + end + if lp == NumQuest + EditHandle(lp)=uicontrol(InputFig , ... + EdInfo , ... + 'Max' ,NumLines(lp,1) , ... + 'Position' ,[ TxtXOffset EditYOffset(lp) TxtWidth EditHeight(lp)], ... + 'String' ,DefAns{lp} , ... + 'Tag' ,'Edit' , ... + 'KeyPressFcn',@doFigureKeyPress ... + ); + else + EditHandle(lp)=uicontrol(InputFig , ... + EdInfo , ... + 'Max' ,NumLines(lp,1) , ... + 'Position' ,[ TxtXOffset EditYOffset(lp) TxtWidth EditHeight(lp)], ... + 'String' ,DefAns{lp} , ... + 'Tag' ,'Edit', ... + 'KeyPressFcn',@doSetFocus ... + ); + end + if isHided(lp) + % set(EditHandle(lp),'KeyPressFcn' ,@typeSecureKeyPress); + % set(EditHandle(lp),'UserData' ,''); + % set(EditHandle(lp),'FontName', 'Wingdings', 'FontWeight', 'bold'); + + jPasswordField = javax.swing.JPasswordField(DefAns{lp}); % default password arg is optional + jPasswordField = javaObjectEDT(jPasswordField); + handles=get(EditHandle(lp)); + jhPasswordField = javacomponent(jPasswordField,handles.Position,InputFig); + end + + QuestHandle(lp)=text('Parent' ,AxesHandle, ... + TextInfo , ... + 'Position' ,[ TxtXOffset QuestYOffset(lp)], ... + 'String' ,WrapQuest{lp} , ... + 'Interpreter',Interpreter , ... + 'Tag' ,'Quest' ... + ); + + MinWidth = max(QuestWidth(:)); + if (size(NumLines,2) == 2) + % input field width has been specified. + inputWidthSpecified = true; + EditWidth = setcolumnwidth(EditHandle(lp), NumLines(lp,1), NumLines(lp,2)); + MinWidth = max(MinWidth, EditWidth); + end + % Get the extent of the text object. See g1008152 + questExtent = get(QuestHandle(lp), 'Extent'); + MinWidth = max(MinWidth, questExtent(3)); + FigWidth=max(FigWidth, MinWidth+2*DefOffset); + +end % for lp + +% fig width may have changed, update the edit fields if they dont have user specified widths. +if ~inputWidthSpecified + TxtWidth=FigWidth-2*DefOffset; + for lp=1:NumQuest + set(EditHandle(lp), 'Position', [TxtXOffset EditYOffset(lp) TxtWidth EditHeight(lp)]); + end +end + +FigPos=get(InputFig,'Position'); + +FigWidth=max(FigWidth,2*(BtnWidth+DefOffset)+DefOffset); +FigPos(1)=0; +FigPos(2)=0; +FigPos(3)=FigWidth; +FigPos(4)=FigHeight; + +set(InputFig,'Position',mygetnicedialoglocation(FigPos,get(InputFig,'Units')),'KeyPressFcn',@doFigureKeyPress); + +OKHandle=uicontrol(InputFig , ... + BtnInfo , ... + 'Position' ,[ FigWidth-2*BtnWidth-2*DefOffset DefOffset BtnWidth BtnHeight ] , ... + 'KeyPressFcn',@doControlKeyPress , ... + 'String' ,getString(message('MATLAB:uistring:popupdialogs:OK')) , ... + 'Callback' ,@doCallback , ... + 'Tag' ,'OK' , ... + 'UserData' ,'OK' ... + ); + +mysetdefaultbutton(InputFig, OKHandle); + +CancelHandle=uicontrol(InputFig , ... + BtnInfo , ... + 'Position' ,[ FigWidth-BtnWidth-DefOffset DefOffset BtnWidth BtnHeight ] , ... + 'KeyPressFcn',@doControlKeyPress , ... + 'String' ,getString(message('MATLAB:uistring:popupdialogs:Cancel')) , ... + 'Callback' ,@doCallback , ... + 'Tag' ,'Cancel' , ... + 'UserData' ,'Cancel' ... + ); %#ok + +handles = guihandles(InputFig); +handles.MinFigWidth = FigWidth; +handles.FigHeight = FigHeight; +handles.TextMargin = 2*DefOffset; +guidata(InputFig,handles); +set(InputFig,'ResizeFcn', {@doResize, inputWidthSpecified}); + +% make sure we are on screen +movegui(InputFig) + +% if there is a figure out there and it's modal, we need to be modal too +if ~isempty(gcbf) && strcmp(get(gcbf,'WindowStyle'),'modal') + set(InputFig,'WindowStyle','modal'); +end + +%Set up Segment icon +setupicon(InputFig); + +set(InputFig,'Visible','on'); +drawnow; + +if ~isempty(EditHandle) + uicontrol(EditHandle(1)); +end + +if ishghandle(InputFig) + % Go into uiwait if the figure handle is still valid. + % This is mostly the case during regular use. + c = matlab.ui.internal.dialog.DialogUtils.disableAllWindowsSafely(); + uiwait(InputFig); + delete(c); +end + +% Check handle validity again since we may be out of uiwait because the +% figure was deleted. +if ishghandle(InputFig) + Answer={}; + if strcmp(get(InputFig,'UserData'),'OK') + Answer=cell(NumQuest,1); + pause(0.001) + for lp=1:NumQuest + if isHided(lp) + Answer(lp)=cellstr(jPasswordField.getPassword()'); + else + Answer(lp) = get(EditHandle(lp),{'String'}); + end + end + end + delete(InputFig); +else + Answer = {}; +end +drawnow; % Update the view to remove the closed figure (g1031998) + +function doSetFocus(obj, evd) +switch(evd.Key) + case {'return'} + gdata = guidata(obj.Parent); + pos = obj.Position; + currentedt = 0; + for lp = 1:length(gdata.Edit) + edtpos = get(gdata.Edit(lp),'Position'); + if edtpos == pos + currentedt = lp; + break + end + end + if currentedt > 1 + %reset focus to the next edit + drawnow + uicontrol(gdata.Edit(lp-1)) + end +end + +function doFigureKeyPress(obj, evd) %#ok +switch(evd.Key) + case {'return'} + set(gcbf,'UserData','OK'); + uiresume(gcbf); + case {'escape'} + delete(gcbf); +end + +function doControlKeyPress(obj, evd) +switch(evd.Key) + case {'return'} + if ~strcmp(get(obj,'UserData'),'Cancel') + set(gcbf,'UserData','OK'); + uiresume(gcbf); + else + delete(gcbf) + end + case 'escape' + delete(gcbf) +end + +function doCallback(obj, evd) %#ok +if ~strcmp(get(obj,'UserData'),'Cancel') + set(gcbf,'UserData','OK'); + uiresume(gcbf); +else + delete(gcbf) +end + +function typeSecureKeyPress(obj, evd) +% key = unicode2native(evd.Key) +key = evd.Key; +switch key + case 'backspace' + eraseedit(obj) + case 'delete' + eraseedit(obj) + case 'return' + % need to be implemented for ctrl+V and return + otherwise + if length(key)==1 + writeinedit(obj,evd.Character); + end +end + +function writeinedit(h,key) +strout = get(h, 'UserData'); +strout = [strout key]; +set(h,'UserData',strout); + +function eraseedit(h) +strout = get(h, 'UserData'); +if not(isempty(strout)) + strout=strout(1:(end-1)); + set(h,'userdata',strout); +end + +%--------------------------------------------- +function doResize(FigHandle, evd, multicolumn) +%--------------------------------------------- +%resize + +Data=guidata(FigHandle); + +resetPos = false; + +FigPos = get(FigHandle,'Position'); +FigWidth = FigPos(3); +FigHeight = FigPos(4); + +% the current and the target sizes are considered equal +% if the difference is less then 1 pixel +% (Position property values can be doubles due to other units, +% and the non integer values show up due to conversions/round offs) +widthDiff = Data.MinFigWidth - FigWidth; +if widthDiff >= 1 + FigWidth = Data.MinFigWidth; + FigPos(3) = Data.MinFigWidth; + resetPos = true; +end + +% make sure edit fields use all available space if +% number of columns is not specified in dialog creation. +if ~multicolumn + for lp = 1:length(Data.Edit) + EditPos = get(Data.Edit(lp),'Position'); + EditPos(3) = FigWidth - Data.TextMargin; + set(Data.Edit(lp),'Position',EditPos); + end +end + + +% the current and the target sizes are considered equal +% if the difference is less then 1 pixel +% (Position property values can be doubles due to other units, +% and the non integer values show up due to conversions/round offs) +heightDiff = abs(FigHeight - Data.FigHeight); +if heightDiff >= 1 + FigPos(4) = Data.FigHeight; + resetPos = true; +end + +if resetPos + set(FigHandle,'Position',FigPos); +end + + +%------------------------------------------------------ +% set pixel width given the number of columns +function EditWidth = setcolumnwidth(object, rows, cols) +%------------------------------------------------------ +% Save current Units and String. +old_units = get(object, 'Units'); +old_string = get(object, 'String'); +old_position = get(object, 'Position'); + +set(object, 'Units', 'pixels') +set(object, 'String', char(ones(1,cols)*'x')); + +new_extent = get(object,'Extent'); +if (rows > 1) + % For multiple rows, allow space for the scrollbar + new_extent = new_extent + 19; % Width of the scrollbar +end +new_position = old_position; +new_position(3) = new_extent(3) + 1; +set(object, 'Position', new_position); + +% reset string and units +set(object, 'String', old_string, 'Units', old_units); + +EditWidth = new_extent(3); + + +%------------------------------------------------ +function mysetdefaultbutton(figHandle, btnHandle) +%------------------------------------------------ +% Own version of Matlab setdefaultbutton +%SETDEFAULTBUTTON Set default button for a figure. +% SETDEFAULTBUTTON(BTNHANDLE) sets the button passed in to be the default button +% (the button and callback used when the user hits "enter" or "return" +% when in a dialog box. + +% Nargin Check +narginchk(1,2) + +if (usejava('awt') == 1) + % We are running with Java Figures + useJavaDefaultButton(figHandle, btnHandle) +else + % We are running with Native Figures + useHGDefaultButton(figHandle, btnHandle); +end + +%--------------------------------------- +function useJavaDefaultButton(figH, btnH) +%--------------------------------------- +% Get a UDD handle for the figure. +fh = handle(figH); +% Call the setDefaultButton method on the figure handle +fh.setDefaultButton(btnH); + +%---------------------------------------- +function useHGDefaultButton(~, btnHandle) +%--------------------------------------- +% First get the position of the button. +btnPos = getpixelposition(btnHandle); + +% Next calculate offsets. +leftOffset = btnPos(1) - 1; +bottomOffset = btnPos(2) - 2; +widthOffset = btnPos(3) + 3; +heightOffset = btnPos(4) + 3; + +% Create the default button look with a uipanel. +% Use black border color even on Mac or Windows-XP (XP scheme) since +% this is in natve figures which uses the Win2K style buttons on Windows +% and Motif buttons on the Mac. +h1 = uipanel(get(btnHandle, 'Parent'), 'HighlightColor', 'black', ... + 'BorderType', 'etchedout', 'units', 'pixels', ... + 'Position', [leftOffset bottomOffset widthOffset heightOffset]); + +% Make sure it is stacked on the bottom. +uistack(h1, 'bottom'); + + +%------------------------------------------------------------------------ +function figure_size = mygetnicedialoglocation(figure_size, figure_units) +%------------------------------------------------------------------------ +% own version of getnicedialoglocation +% adjust the specified figure position to fig nicely over GCBF +% or into the upper 3rd of the screen + +parentHandle = gcbf; +convertData.destinationUnits = figure_units; +if ~isempty(parentHandle) + % If there is a parent figure + convertData.hFig = parentHandle; + convertData.size = get(parentHandle,'Position'); + convertData.sourceUnits = get(parentHandle,'Units'); + c = []; +else + % If there is no parent figure, use the root's data + % and create a invisible figure as parent + convertData.hFig = figure('visible','off'); + convertData.size = get(0,'ScreenSize'); + convertData.sourceUnits = get(0,'Units'); + c = onCleanup(@() close(convertData.hFig)); +end + +% Get the size of the dialog parent in the dialog units +container_size = hgconvertunits(convertData.hFig, convertData.size ,... + convertData.sourceUnits, convertData.destinationUnits, get(convertData.hFig,'Parent')); + +delete(c); + +figure_size(1) = container_size(1) + 1/2*(container_size(3) - figure_size(3)); +figure_size(2) = container_size(2) + 2/3*(container_size(4) - figure_size(4)); diff --git a/source/myinputstruct.m b/source/myinputstruct.m new file mode 100644 index 0000000..0f18d8a --- /dev/null +++ b/source/myinputstruct.m @@ -0,0 +1,414 @@ +function [outs,ok] = myinputstruct(s,tit,width) +%Automatically create input dialogs with Medviso style +%This function replaces the old inputstruct. +% +%MYINPUTSTRUCT(S,TITLE,WIDTH) +%- S = Struct, see below for example. +%- TIT = Title string. +%- WIDTH = Width of editbox (optional, default = 10) +% +%Note that the function does not call translation and you need to do this +%manually before calling the function. +% +%Example: +%s = []; %reset +%s(1).Field = 'Name'; +%s(1).Label = dprintf('Name'); %Use dprintf only if you want the input to be translated. +%s(1).Default = 'Box'; +%s(2).Field = 'H'; +%s(2).Label = dprintf('Height [mm]'); +%s(2).Default = 10; +%s(2).Limits = [0,10]; +%s(3).Field = 'W'; +%s(3).Label = dprintf('Width [mm]'); +%s(3).Default = 20; +%s(3).Limits = [0,30]; +%s(4).Field = 'Visible'; +%s(4).Label = dprintf('Visible'); +%s(4).Default = true; +%[outs,ok] = myinputstruct(s,'Input box parameters',10); %10 is 10 characters minimum +% +%If user press cancel or close then ok = false; +% +%Optional fields +%- Tooltip, sets Tooltip string + +%REMOVED FUNCTIONALITY +%- Limits (default [-inf inf]) +%- ValueDisplayFormat (default '%11.4g') +%- LowerLimitInclusive (default 'on') +%- UpperLimitInclusive (default 'on') +% +%Hint to input decimals use any of the int/uint classes + +%Einar Heiberg + +%left to do: +%- put limits back. +%- listbox support +%- DONE ok button +%- DONE correct colors +%- DONE add translation + +outs = []; + +if nargin<1 + error('Invalid input.'); +end + +%Error checks +if ~isfield(s,'Field') + disp('Required fieldname Field is missing.'); + error('Invalid input.'); +end + +if ~isfield(s,'Label') + disp('Required fieldname Label is missing.'); + error('Invalid input.'); +end + +if ~isfield(s,'Default') + for loop = 1:length(s) + s(loop).Default = ''; + end +end + +if ~isfield(s,'Tooltip') + for loop = 1:length(s) + s(loop).Tooltip = ''; + end +end + +% if ~isfield(s,'ValueDisplayFormat') +% for loop = 1:length(s) +% s(loop).ValueDisplayFormat = '%11.4g'; +% end +% end +% +% if ~isfield(s,'Limits') +% for loop = 1:length(s) +% s(loop).Limits = [-inf inf]; +% end +% end +% if ~isfield(s,'LowerLimitInclusive') +% for loop = 1:length(s) +% s(loop).LowerLimitInclusive = 'on'; +% end +% end +% +% if ~isfield(s,'UpperLimitInclusive') +% for loop = 1:length(s) +% s(loop).UpperLimitInclusive = 'on'; +% end +% end +% +% %Check validity +% for loop = 1:length(s) +% if isempty(s(loop).Limits) +% s(loop).Limits = [-inf inf]; +% end +% end +% +% for loop = 1:length(s) +% if isempty(s(loop).LowerLimitInclusive) +% s(loop).ToolTip = 'on'; +% end +% end +% +% for loop = 1:length(s) +% if isempty(s(loop).UpperLimitInclusive) +% s(loop).ToolTip = 'on'; +% end +% end +% +% for loop = 1:length(s) +% if isempty(s(loop).ValueDisplayFormat) +% s(loop).ValueDisplayFormat = '%11.4g'; +% end +% end + +for loop = 1:length(s) + if isempty(s(loop).Tooltip) + s(loop).ToolTip = ''; + end +end + +for loop = 1:length(s) + if isempty(s(loop).Label) + s(loop).Label = s(loop).Field; + end +end + +if nargin<2 + tit = ''; +end + +if nargin<3 + width = 10; %characters +end + +%Call creation function +fig = createit(s,dprintf('%s',tit),width); %There is a uiwait so it returns when user clicked ok + +%Get data +if ~ishandle(fig) || isequal(fig.UserData,'Cancelled') + ok = false; + %Copy default and setup + for loop = 1:length(s) + outs.(s(loop).Field) = s(loop).Default; + end + +else + [outs,ok] = parse(fig,s); +end + +%Close the figure +if ishandle(fig) + delete(fig); +end + +%-------------------------------- +function [outs,ok] = parse(fig,s) +%-------------------------------- +%Gets the edited results + +outs = []; +ok = true; + +%Copy default and setup +for loop = 1:length(s) + outs.(s(loop).Field) = s(loop).Default; +end + +c = fig.Children; + +errors = false; +message = ''; +%Loop over elements to get them +for loop = 1:length(c) + ud = c(loop).UserData; + if ~isempty(ud) + + %Loop over to find. A bit uggly but who cares, fast enough + id = 1; + for sloop = 1:length(s) + if isequal(s(sloop).Field,ud) + id = sloop; + end + end + + %Assign it + if isnumeric(s(id).Default) + outs.(ud) = str2double(c(loop).String); + if isnan(outs.(ud)) + errors = true; + message = dprintf('Invalid response for %s',s(id).Label); + end + end + + if islogical(s(id).Default) + outs.(ud) = logical(c(loop).Value); + end + + if ischar(s(id).Default) + outs.(ud) = c(loop).String; + end + + end +end + +if errors + ok = false; + myfailed(message); +end + +%-------------------------------------- +function fig = createit(s,tit,minchars) +%-------------------------------------- +%Creates the figure and populates it + +global DATA + +%get color settings +bc = DATA.GUISettings.BackgroundColor; +fc = DATA.GUISettings.ForegroundColor; + +fig = figure('Name',tit,... + 'Color',bc,... + 'UserData','Cancelled',... + 'MenuBar','none',... + 'NumberTitle','off'); %set userData to cancelled, if not then change later + +%Set up Segment icon +setupicon(fig); + +%Count number of elements +n = length(s); + +%margins +topmarg = 20; +bottommarg = 20; +ymarg = 15; %distance between lines + +leftmarg = 10; +rightmarg = 10; +xmarg = 10; %distance between columns + +%constants +fontsize = 14; +fontf = 12; %width of character in pixels +rowheight = 25; + +%Loop over all to compute width and height +labelwidth = zeros(1,n+1); +boxwidth = zeros(1,n+1); +height = zeros(1,n+1); +type = cell(1,n+1); + +for loop = 1:n + switch class(s(loop).Default) + case {'single','double','int8','uint8','int16','uint16','int32','uint32','int64','uint64'} + %Numeric + labelwidth(loop) = length(s(loop).Label)*fontf; + boxwidth(loop) = max(length(strtrim(sprintf('%11.4g',s(loop).Default))),minchars)*fontf; + height(loop) = rowheight; + type{loop} = 'numeric'; + case 'logical' + labelwidth(loop) = (2+length(s(loop).Label))*fontf; + boxwidth(loop) = 0; + height(loop) = rowheight; + type{loop} = 'logical'; + case 'char' + labelwidth(loop) = length(s(loop).Label)*fontf; + boxwidth(loop) = max(length(s(loop).Default),minchars)*fontf; + height(loop) = rowheight; + type{loop} = 'char'; + end +end + +%Add button +labelwidth(n+1) = 300; +boxwidth(n+1) = 0; +height(n+1) = 20; + +maxlabelwidth = max(labelwidth(1:n)); +maxboxwidth = max(boxwidth(1:n))+xmarg; +cumheight = [0 cumsum(height+ymarg)]; + +%Required width and height +reqw = leftmarg+maxlabelwidth+xmarg+maxboxwidth+rightmarg; +reqh = topmarg+sum(height)+n*ymarg+bottommarg; + +%Get and set size +p = fig.Position; +fig.Position = [p(1) p(2) reqw reqh]; %later center + +u = zeros(1,length(s)); +for loop = 1:length(s) + + %Compute y position + posy = reqh-(topmarg+cumheight(loop))-bottommarg; + posx = leftmarg+maxlabelwidth+xmarg; + + %Fix stri + switch type{loop} + case 'numeric' + %Numeric + stri = sprintf('%11.4g',s(loop).Default); + stri = stri(stri~=' '); + u(loop) = uicontrol(... + 'parent',fig,... + 'Style','edit',... + 'UserData',s(loop).Field,... + 'TooltipString',sprintf('%s',s(loop).Tooltip),... + 'Position',[posx posy maxboxwidth height(loop)],... + 'HorizontalAlignment','center',... + 'String',stri,... + 'ForegroundColor',fc,... + 'BackgroundColor',bc,... + 'Fontsize',fontsize); + case 'logical' + stri = s(loop).Label; + u(loop) = uicontrol(... + 'parent',fig,... + 'Style','checkbox',... + 'UserData',s(loop).Field,... + 'TooltipString',sprintf('%s',s(loop).Tooltip),... + 'Position',[leftmarg posy maxlabelwidth height(loop)],... + 'String',stri,... + 'Value',s(loop).Default,... + 'ForegroundColor',fc,... + 'BackgroundColor',bc,... + 'Fontsize',fontsize); + case 'char' + stri = s(loop).Default; + u(loop) = uicontrol(... + 'parent',fig,... + 'Style','edit',... + 'UserData',s(loop).Field,... + 'TooltipString',sprintf('%s',s(loop).Tooltip),... + 'Position',[posx posy maxboxwidth height(loop)],... + 'HorizontalAlignment','left',... + 'String',stri,... + 'ForegroundColor',fc,... + 'BackgroundColor',bc,... + 'Fontsize',fontsize); + end + + %Add the label name + if ~isequal(type{loop},'logical') + uicontrol(fig,... + 'Style','text',... %note do not add userdata here + 'TooltipString',sprintf('%s',s(loop).Tooltip),... + 'Position',[leftmarg posy maxlabelwidth+xmarg height(loop)],... + 'Stri',sprintf('%s',s(loop).Label),... + 'HorizontalAlignment','left',... + 'ForegroundColor',fc,... + 'BackgroundColor',bc,... + 'Fontsize',fontsize); + end + +end + +posx = leftmarg; +posy = reqh-(topmarg+cumheight(loop+1))-bottommarg; + +%Add cancel button +uicontrol(fig,... + 'Style','pushbutton',... + 'Position',[posx posy 100 height(loop+1)],... + 'Callback', @(u,v)cancel_Callback(u,v),... + 'String',dprintf('Cancel'),... + 'ForegroundColor',fc,... + 'BackgroundColor',bc,... + 'Fontsize',fontsize); + +%Add ok button +%[reqw-50-rightm posy-7 50 height(n+1)] +uicontrol(fig,... + 'style','pushbutton',... + 'Position',[reqw-rightmarg-50 posy 50 height(loop+1)],... + 'Callback', @(u,v)ok_Callback(u,v),... + 'Stri',dprintf('Ok'),... + 'ForegroundColor',fc,... + 'BackgroundColor',bc,... + 'Fontsize',fontsize); + +%activate uiwait to wait for user selection until user clicks cancel or ok. +uiwait(fig); + +%---------------------------- +function cancel_Callback(h,~) +%---------------------------- +%If cancel then ... + +uiresume(h.Parent); +h.Parent.UserData = 'Cancelled'; + +%------------------------ +function ok_Callback(h,~) +%------------------------ +%Callback function, just resume + +uiresume(h.Parent); +h.Parent.UserData = ''; diff --git a/source/mymenu.fig b/source/mymenu.fig index 4103805..af904d0 100644 Binary files a/source/mymenu.fig and b/source/mymenu.fig differ diff --git a/source/mymenu.m b/source/mymenu.m index 0dc7a9f..f7c4b52 100644 --- a/source/mymenu.m +++ b/source/mymenu.m @@ -1,5 +1,6 @@ function [varargout] = mymenu(header,varargin) -%m = MYMENU(header,options,defaultstring) +%m = MYMENU(header,items,defaultstring) +%m = MYMENU(header,items,defaultstring,maxselections) %m = MYMENU(header,item1,item2,item3,...) % %Same as menu, but with the following additions: @@ -7,6 +8,8 @@ %- modal display %- can use default string %- last optional argument is figure handle +% +%See also MYINPUTSTRUCT, YESNO %Einar Heiberg global DATA @@ -15,14 +18,13 @@ if nargout>0 varargout = cell(1,1); -end; +end if isa(DATA, 'maingui') && DATA.Testing testing = DATA.Testing; else testing = false; -end; - +end if testing %If testing then also DATA.Buffer should exist @@ -34,21 +36,24 @@ %Test of warning and nbr of options (one less than cell size) pushtobuffer('Warnings',sprintf('%d %s',numel(varargin{1})-1,header)); v = 2; - end; + end varargout{1}=v; return; end %Check if special commands switch header +% //case 'ok' +% print('ok pressed') case '_close' closehelper(handles); if nargout>0 varargout{1} = handles.m; %return; end return - case '_selection' - %--- User has pressed selection + case {'_selection','ok'} + %--- User has pressed selection or has pressed OK button to confirm + %selection handles = selectionhelper(handles); if nargout>0 varargout{1} = handles.m; %return; @@ -60,13 +65,13 @@ varargout{1} = handles.m; %return; end return; -end; %End of case clause +end %End of case clause %--- Init if got to here if nargin<2 myfailed('Too few input arguments.'); return; -end; +end if length(varargin)>1 %Last argument is handle to figure. @@ -84,7 +89,7 @@ fighandle = varargin{1}{n}; varargin = varargin{1}(1:(n-1)); %Remove last... else - fighandle =[]; + fighandle = []; end else fighandle = []; @@ -98,12 +103,12 @@ default = varargin{2}; else default = ''; - end; + end else options = cell(1,length(varargin)); [options{:}] = deal(varargin{:}); default = ''; -end; +end % %translation % header = translation.dictionary(header); @@ -113,11 +118,10 @@ %Call initialization code. handles = init(header,fighandle,options,default); -translation.translatealllabels(handles.fig); try uiwait(handles.fig); %wait until terminates catch %#ok -end; +end if nargout>0 varargout{1} = handles.m; %return; @@ -140,11 +144,11 @@ if isequal(key,'return') handles = selectionhelper(handles); return; -end; +end if isempty(key) return; -end; +end %--- Check for special keys switch key @@ -162,7 +166,7 @@ closehelper(handles); handles.m = 0; return; -end; +end %--- Find menu items beginning with the same letter. ind = []; @@ -170,10 +174,10 @@ temp = handles.options{loop}; if (~isempty(temp)) if isequal(lower(temp(1)),key(1)) - ind = [ind loop]; - end; - end; -end; + ind = [ind loop]; %#ok + end + end +end if isempty(ind) %Try to loop from begining @@ -181,26 +185,28 @@ temp = handles.options{loop}; if (~isempty(temp)) if isequal(lower(temp(1)),key(1)) - ind = [ind loop]; - end; - end; - end; -end; + ind = [ind loop]; %#ok + end + end + end +end if isempty(ind) return; -end; +end set(handles.menulistbox,'value',ind(1)); %---------------------------- function closehelper(handles) %---------------------------- +%Close helper + set(handles.fig,'closerequestfcn',''); try delete(handles.fig); catch %#ok -end; +end %------------------------------- function keypressed(fignum,evnt) %#ok @@ -211,66 +217,73 @@ function keypressed(fignum,evnt) %#ok %---------------------------------------------- function handles = init(header,fighandle,options,default) %---------------------------------------------- +%Initialize -fig = openfig('mymenu.fig','reuse'); -set(fig,'visible','off');%menu not visble until it is horisontally aligned -set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); +fig = openfig('mymenu.fig','reuse','invisible');%menu not visble until it is horisontally aligned +setupicon(fig); +setinterfacecolor(fig); if ~isempty(fighandle) myadjust(fig,fighandle); -end; +end %Extract handles handles = guihandles(fig); handles.fig = fig; handles.header = header; handles.options = options; -handes.default = default; +handles.default = default; handles.m = 0; %default... %Set handles. -set(handles.fig,'name',header); +set(handles.fig,'name',''); % set(handles.fig,'name','Select'); % set(handles.titletext,'String',header); set(handles.menulistbox,'String',options,... - 'Callback','mymenu(''_selection'','''')'); + 'Callback','mymenu(''_selection'','''')',... + 'Fontsize',14); set(handles.menulistbox,'keypressfcn',@keypressed); set(handles.fig,'keypressfcn',@keypressed); +translation.translatealllabels(fig); + %Adjust size p = get(handles.fig,'position'); -extrapixels = 0; +yextrapixels = 0; + if length(handles.options)>5 - extrapixels = 50; -end; + yextrapixels = 50; +end if length(handles.options)>10 - extrapixels = 150; -end; + yextrapixels = 150; +end if length(handles.options)>15 - extrapixels = 250; -end; + yextrapixels = 250; +end if length(handles.options)>20 - extrapixels = 400; -end; -p(4) = p(4)+extrapixels; -p(2) = p(2)-extrapixels; + yextrapixels = 400; +end +p(4) = p(4)+yextrapixels; +p(2) = p(2)-yextrapixels; + + set(handles.fig,'position',p); -pmenu=get(handles.menulistbox,'position'); -ptitle=get(handles.titletext,'position'); +pmenu = get(handles.menulistbox,'position'); +ptitle = get(handles.titletext,'position'); -pmenu(4)=p(4)-ptitle(4)-pmenu(2)-20; -pmenu(2)=pmenu(2);%+extrapixels; +pmenu(4) = p(4)-ptitle(4)-pmenu(2)-20; +pmenu(2) = pmenu(2);%+extrapixels; set(handles.menulistbox,'position',pmenu); -ptitle(2)=p(4)-ptitle(4)-10; -set(handles.titletext,'position',ptitle); +ptitle(2) = p(4)-ptitle(4)-10; +set(handles.titletext,'position',ptitle,'string',header); try if ~isempty(fighandle) myadjust(handles.fig,fighandle); %Horisontal alignment. - end; + end catch %#ok -end; +end set(fig,'visible','on');%menu not visble until it is horisontally aligned %Find default and mark it @@ -279,13 +292,13 @@ function keypressed(fignum,evnt) %#ok for loop=1:length(options) if isequal(options{loop},default) defaultpos = loop; - end; - end; + end + end if ~isempty(defaultpos) set(handles.menulistbox,'value',defaultpos); - end; -end; + end +end %------------------ function showout(d) @@ -296,9 +309,9 @@ function showout(d) recordmacro = DATA.RecordMacro; else recordmacro = false; -end; +end if recordmacro macro_helper('put',sprintf('pushtobuffer(''Mymenu'',%d); %%select menu item',d)); macro_helper('switchorder'); %We need to store data in buffer before the callback -end; \ No newline at end of file +end diff --git a/source/mymenumultiplechoice.m b/source/mymenumultiplechoice.m new file mode 100644 index 0000000..8173965 --- /dev/null +++ b/source/mymenumultiplechoice.m @@ -0,0 +1,322 @@ +function [varargout] = mymenumultiplechoice(header,varargin) +%m = MYMENU(header,items,defaultstring) +%m = MYMENU(header,items,defaultstring,maxselections) +%m = MYMENU(header,item1,item2,item3,...) +% +%Same as menu, but with the following additions: +%- more elegant! uses keyboard to select items. +%- modal display +%- can use default string +%- last optional argument is figure handle + +%Einar Heiberg +global DATA + +persistent handles + +if nargout>0 + varargout = cell(1,1); +end + +if isa(DATA, 'maingui') && DATA.Testing + testing = DATA.Testing; +else + testing = false; +end + + +if testing + %If testing then also DATA.Buffer should exist + v = popfrombuffer('Mymenu'); + if isempty(v) + myfailed('Menu buffer is empty.'); + return; + elseif isnan(v) + %Test of warning and nbr of options (one less than cell size) + pushtobuffer('Warnings',sprintf('%d %s',numel(varargin{1})-1,header)); + v = 2; + end + varargout{1}=v; + return; +end + +%Check if special commands +switch header +% //case 'ok' +% print('ok pressed') + case {'cancel'} + %--- User has pressed selection or has pressed OK button to confirm + %selection + closehelper(handles); + handles.m = []; + if nargout>0 + varargout{1} = handles.m; + end + return; + case '_close' + closehelper(handles); + if nargout>0 + varargout{1} = handles.m; %return; + end + return + case {'_selection'} + %--- User has pressed selection or has pressed OK button to confirm + %selection + handles = selectionhelper(handles); + if nargout>0 + varargout{1} = handles.m; %return; + end + return; + case '_key' + handles = keyhelper(handles,varargin{1}); + if nargout>0 + varargout{1} = handles.m; %return; + end + return; +end %End of case clause + +%--- Init if got to here +if nargin<2 + myfailed('Too few input arguments.'); + return; +end + +if length(varargin)>1 + %Last argument is handle to figure. + n = length(varargin); + if ishandle(varargin{n}) + fighandle = varargin{n}; + varargin = varargin(1:(n-1)); %Remove last... + else + fighandle =[]; + end +else + if isa(varargin{1},'cell') + n = length(varargin{1}); + if ishandle(varargin{1}{n}) + fighandle = varargin{1}{n}; + varargin = varargin{1}(1:(n-1)); %Remove last... + else + fighandle = []; + end + else + fighandle = []; + end +end + +%Extract paramters +if iscell(varargin{1}) + options = varargin{1}; + if length(varargin)==2 + default = varargin{2}; + else + default = ''; + end +else + options = cell(1,length(varargin)); + [options{:}] = deal(varargin{:}); + default = ''; +end + +% %translation +% header = translation.dictionary(header); +% for k=1:numel(options) +% options{k} = translation.dictionary(options{k}); +% end + +%Call initialization code. +handles = init(header,fighandle,options,default); +try + uiwait(handles.fig); %wait until terminates +catch %#ok +end + +if nargout>0 + varargout{1} = handles.m; %return; + showout(handles.m); +end +flushlog; + +%------------------------------------------ +function handles = selectionhelper(handles) +%------------------------------------------ +%Get selection +handles.m = mygetlistbox(handles.menulistbox); +% closehelper(handles); + +%---------------------------------------- +function handles = keyhelper(handles,key) +%---------------------------------------- + +%--- If pressed return, then take currently selected. +if isequal(key,'return') + handles = selectionhelper(handles); + closehelper(handles); + return; +end + +if isempty(key) || contains(key,'shift') || contains(key,'ctrl') + return; +end + +%--- Check for special keys +switch key + case 'uparrow' + v = mygetlistbox(handles.menulistbox); + v = max(v-1,1); + set(handles.menulistbox,'value',v); + return; + case 'downarrow' + v = mygetlistbox(handles.menulistbox); + v = min(v+1,length(handles.options)); + set(handles.menulistbox,'value',v); + return; + case 'escape' + closehelper(handles); + handles.m = []; + return; +end + +%--- Find menu items beginning with the same letter. +ind = []; +for loop=(mygetlistbox(handles.menulistbox)+1):length(handles.options) + temp = handles.options{loop}; + if (~isempty(temp)) + if isequal(lower(temp(1)),key(1)) + ind = [ind loop]; + end + end +end + +if isempty(ind) + %Try to loop from begining + for loop=1:length(handles.options) + temp = handles.options{loop}; + if (~isempty(temp)) + if isequal(lower(temp(1)),key(1)) + ind = [ind loop]; + end + end + end +end + +if isempty(ind) + return; +end + +set(handles.menulistbox,'value',ind(1)); + +%---------------------------- +function closehelper(handles) +%---------------------------- +set(handles.fig,'closerequestfcn',''); +try + delete(handles.fig); +catch %#ok +end + +%------------------------------- +function keypressed(fignum,evnt) %#ok +%------------------------------- +key = getkey(evnt); +mymenumultiplechoice('_key',key); + +%---------------------------------------------- +function handles = init(header,fighandle,options,default) +%---------------------------------------------- + +fig = openfig('mymenu.fig','reuse','invisible');%menu not visble until it is horisontally aligned +setupicon(fig); +setinterfacecolor(fig); +if ~isempty(fighandle) + myadjust(fig,fighandle); +end + +%Extract handles +handles = guihandles(fig); +handles.fig = fig; +handles.header = header; +handles.options = options; +handles.default = default; +handles.m = 0; %default... + +%Set handles. +set(handles.fig,'name',translation.dictionary(header)); +% set(handles.fig,'name','Select'); +hintstr = dprintf('Use CTRL + click to choose multiple options'); +set(handles.titletext,'String',hintstr); +set(handles.menulistbox,'String',options,'Max',10,... + 'Callback','mymenumultiplechoice(''_selection'','''')'); +set(handles.menulistbox,'keypressfcn',@keypressed); +set(handles.fig,'keypressfcn',@keypressed,'CloseRequestFcn','mymenumultiplechoice(''_close'')'); +set(handles.okpushbutton,'Callback','mymenumultiplechoice(''_close'')'); +set(handles.cancelpushbutton,'Callback','mymenumultiplechoice(''cancel'')'); + +translation.translatealllabels(fig); + +%Adjust size +p = get(handles.fig,'position'); +extrapixels = 0; +if length(handles.options)>5 + extrapixels = 50; +end +if length(handles.options)>10 + extrapixels = 150; +end +if length(handles.options)>15 + extrapixels = 250; +end +if length(handles.options)>20 + extrapixels = 400; +end +p(4) = p(4)+extrapixels; +p(2) = p(2)-extrapixels; +set(handles.fig,'position',p); + +pmenu=get(handles.menulistbox,'position'); +ptitle=get(handles.titletext,'position'); + +pmenu(4)=p(4)-ptitle(4)-pmenu(2)-20; +pmenu(2)=pmenu(2);%+extrapixels; +set(handles.menulistbox,'position',pmenu); + +ptitle(2)=p(4)-ptitle(4)-10; +set(handles.titletext,'position',ptitle); + +try + if ~isempty(fighandle) + myadjust(handles.fig,fighandle); %Horisontal alignment. + end +catch %#ok +end +set(fig,'visible','on');%menu not visble until it is horisontally aligned + +%Find default and mark it +if ~isempty(default) + defaultpos = []; + for loop=1:length(options) + if isequal(options{loop},default) + defaultpos = loop; + end + end + + if ~isempty(defaultpos) + set(handles.menulistbox,'value',defaultpos); + end +end + +%------------------ +function showout(d) +%------------------ +global DATA + +if isa(DATA, 'maingui') && DATA.RecordMacro + recordmacro = DATA.RecordMacro; +else + recordmacro = false; +end + +if recordmacro + macro_helper('put',sprintf('pushtobuffer(''Mymenu'',%d); %%select menu item',d)); + macro_helper('switchorder'); %We need to store data in buffer before the callback +end diff --git a/source/mymkdir.m b/source/mymkdir.m index 0132930..7e9bdf7 100644 --- a/source/mymkdir.m +++ b/source/mymkdir.m @@ -13,13 +13,13 @@ sucess = true; if ~exist(d,'dir') sucess = mkdir(d); -end; +end varargout = cell(1,nargout); if nargout>0 varargout{1} = sucess; -end; +end if nargout>1 error('No more than one output argument.'); -end; +end diff --git a/source/mymovefile.m b/source/mymovefile.m index 0f9894e..27c62f7 100644 --- a/source/mymovefile.m +++ b/source/mymovefile.m @@ -16,7 +16,7 @@ varargout = cell(1,nargout); if nargout>0 varargout{1} = status; -end; +end if nargout>1 varargout{2} = message; -end; +end diff --git a/source/mymsgbox.m b/source/mymsgbox.m index 6be9365..b0292d4 100644 --- a/source/mymsgbox.m +++ b/source/mymsgbox.m @@ -1,4 +1,4 @@ -function mymsgbox(stri,title,fighandle) +function h = mymsgbox(stri,title,fighandle) %MYMSGBOX Helper function, works as MSGBOX % %MYMSGBOX(STRI,TITLE,[ALIGNMENT]) @@ -17,30 +17,70 @@ function mymsgbox(stri,title,fighandle) if nargin<2 title = ''; fighandle=[]; -end; +end stri = translation.dictionary(stri); +title = translation.dictionary(title); try if DATA.Pref.DoNotAsk %If do not ask then also do not display mydisp(dprintf('Message: %s\n',stri)); return; - end; + end catch %#ok -end; +end try mydisp(dprintf('Message: %s\n',stri)); catch %#ok - disp(sprintf('Message: %s\n',stri)); -end; + dispstri = tools('maskpatientstrings',stri); + fprintf('Message: %s\n\n',dispstri); +end keystroke = popfrombuffer('KeyStroke'); +h = []; if isempty(keystroke) - h = msgbox(stri,title); + if contains(stri,'Your license does not include') + createmode = struct('WindowStyle','modal','Interpreter', 'tex'); + else + createmode = struct('WindowStyle','modal','Interpreter', 'none'); + end + h = msgbox(stri,title,createmode); + try + htext = findobj(h, 'Type', 'Text'); %find text control in dialog + set(htext,'Color',DATA.GUISettings.ForegroundColor,'FontSize',9,'Units','normalized'); + catch me + mydispexception(me) + end + + try + set(h,'Color',DATA.GUISettings.BackgroundColor); + kids = h.Children; + for i=1:length(kids) + try set(kids(i),'BackgroundColor',DATA.GUISettings.BackgroundColor);catch, end + try set(kids(i),'Color',DATA.GUISettings.BackgroundColor);catch, end + try set(kids(i),'ForegroundColor',DATA.GUISettings.ForegroundColor);catch, end + try set(kids(i),'FontSize',12);catch, end + try + kidstyle = kids(i).Style; + if strcmp(kidstyle,'pushbutton') + set(kids(i),'Units','normalized','FontSize',9) + end + catch + end + end + catch me + mydispexception(me) + end + if length(stri) > 40 + ps = get(h,'Position'); + set(h,'Position',[ps(1) ps(2) ps(3)*1.2 ps(4)]) + end + myadjust(h,fighandle); - set(h,'windowstyle','modal'); + % set(h,'windowstyle','modal'); + setupicon(h); %set up Segment icon uiwait(h); try macro_helper('put','pushtobuffer(''KeyStroke'',''ok''); %ok from mymsgbox'); @@ -48,7 +88,7 @@ function mymsgbox(stri,title,fighandle) catch %#ok %Do nothing if this fails. Most likely DATA variable is not %initialized. - end; + end else if isequal(lower(keystroke),'ok') macro_helper('put','pushtobuffer(''KeyStroke'',''ok''); %ok from mymsgbox'); @@ -56,6 +96,6 @@ function mymsgbox(stri,title,fighandle) return; else error('Expected ''ok'' as keystroke'); - end; -end; + end +end flushlog; diff --git a/source/mynormalize.mexw32 b/source/mynormalize.mexw32 deleted file mode 100644 index 96973ec..0000000 Binary files a/source/mynormalize.mexw32 and /dev/null differ diff --git a/source/myopenpdf.m b/source/myopenpdf.m new file mode 100644 index 0000000..7b60c36 --- /dev/null +++ b/source/myopenpdf.m @@ -0,0 +1,22 @@ +function myopenpdf(fileName) +%OPENPDF Opens a PDF file in the appropriate viewer/editor. + +% Copyright 1984-2009 The MathWorks, Inc. +% The same function as Matlabs inbuild function +if ~exist(fileName, 'file') + error(message('MATLAB:openpdf:noSuchFile', fileName)); +end + +if ispc + winopen(fileName); +elseif strncmp(computer,'MAC',3) + unix(['open "' fileName '" &']); +else + command = 'acroread'; + if (usejava('mwt') == 1) + % Get the user's PDF reader from preferences. + command = com.mathworks.services.Prefs.getStringPref('HelpPDF_Reader', command); + command = char(command); + end + unix([command ' "' fileName '" &']); +end \ No newline at end of file diff --git a/source/mypoly2cw.m b/source/mypoly2cw.m index 0b98f19..5117cf6 100644 --- a/source/mypoly2cw.m +++ b/source/mypoly2cw.m @@ -12,6 +12,7 @@ y1=nan(size(y2)); return end + %Check if index order is mostly flipped by convhull that means curve has %mostly clockwise orientation if sum(diff(k(2:end))<0)>length(k)/2 diff --git a/source/myset.m b/source/myset.m index 9c6fe20..9602052 100644 --- a/source/myset.m +++ b/source/myset.m @@ -6,4 +6,4 @@ function myset(handlevec,varargin) handlevec = handlevec(ishandle(handlevec)); if ~isempty(handlevec) set(handlevec,varargin{:}); -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/myuigetdir.m b/source/myuigetdir.m index 8db2797..de5a537 100644 --- a/source/myuigetdir.m +++ b/source/myuigetdir.m @@ -9,11 +9,11 @@ if nargin<1 error('Expected at least one input arguments (prompt).'); -end; +end if nargin<2 titlestr = ''; -end; +end %translation titlestr = translation.dictionary(titlestr); @@ -22,16 +22,16 @@ testing = DATA.Testing; else testing = false; - end; + end if DATA.RecordMacro recordmacro = DATA.RecordMacro; else recordmacro = false; - end; + end else testing = false; recordmacro = false; -end; +end ok = false; if testing @@ -41,17 +41,21 @@ ok = true; else error('No path selection in buffer.'); - end; + end else %Ask user + if DATA.isSiemensVersion + % in Open apps version the path is fixed + pathname = '\\tsclient\c'; + end pathname = uigetdir(pathname, titlestr); if isequal(pathname,0) return; - end; + end ok = true; -end; +end if recordmacro macro_helper('put',sprintf('pushtobuffer(''Dir'',''%s'') ; %%add to buffer',pathname)); macro_helper('switchorder'); %We need to store data in buffer before the callback -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/myurlread.m b/source/myurlread.m index 1595a0f..a9d55aa 100644 --- a/source/myurlread.m +++ b/source/myurlread.m @@ -120,7 +120,8 @@ errormsg = ''; % Determine the protocol (before the ":"). -protocol = urlChar(1:min(find(urlChar==':'))-1); +% protocol = urlChar(1:min(find(urlChar==':'))-1); +protocol = urlChar(1:find(urlChar==':', 1)-1); % Try to use the native handler, not the ice.* classes. switch protocol diff --git a/source/mywaitbarclose.m b/source/mywaitbarclose.m index f225783..5db7ca8 100644 --- a/source/mywaitbarclose.m +++ b/source/mywaitbarclose.m @@ -14,4 +14,4 @@ function mywaitbarclose(varargin) else %Well seems not to be overloaded => maingui.mywaitbarclose(varargin{:}); -end; +end diff --git a/source/mywaitbarmainclose.m b/source/mywaitbarmainclose.m index 78590d1..b949994 100644 --- a/source/mywaitbarmainclose.m +++ b/source/mywaitbarmainclose.m @@ -14,4 +14,4 @@ function mywaitbarmainclose(varargin) else %Well seems not to be overloaded => maingui.mywaitbarmainclose(varargin{:}); -end; +end diff --git a/source/mywaitbarmainstart.m b/source/mywaitbarmainstart.m index cc7c709..831dca2 100644 --- a/source/mywaitbarmainstart.m +++ b/source/mywaitbarmainstart.m @@ -11,7 +11,7 @@ %minimize CPU consumption. Function returns a handle to a %MYWAITBAROBJECT. FIGHANDLE is optional and indicates alignment % -%See also MYWAITBARUPDATE, MYWAITBARCLOSE. +%See also MYWAITBARSET, MYWAITBARUPDATE, MYWAITBARCLOSE. %Einar Heiberg @@ -22,5 +22,5 @@ else %Well seems not to be overloaded => h = maingui.mywaitbarmainstart(varargin{:}); -end; +end diff --git a/source/mywaitbarstart.m b/source/mywaitbarstart.m index 322a1ba..5335faa 100644 --- a/source/mywaitbarstart.m +++ b/source/mywaitbarstart.m @@ -11,7 +11,7 @@ %minimize CPU consumption. Function returns a handle to a %MYWAITBAROBJECT. FIGHANDLE is optional and indicates alignment % -%See also MYWAITBARUPDATE, MYWAITBARCLOSE. +%See also MYWAITBARUPDATE, MYWAITBARSET, MYWAITBARCLOSE. %Einar Heiberg @@ -22,5 +22,5 @@ else %Well seems not to be overloaded => h = maingui.mywaitbarstart(varargin{:}); -end; +end diff --git a/source/mywaitbarupdate.m b/source/mywaitbarupdate.m index 7127808..708e669 100644 --- a/source/mywaitbarupdate.m +++ b/source/mywaitbarupdate.m @@ -5,7 +5,7 @@ %counter one step. Graphic is updated depends on %setting when intializing the structure. % -%See also MYWAITBARSTART, MYWAITBARCLOSE. +%See also MYWAITBARSTART, MYWAITBARSET, MYWAITBARCLOSE. global DATA @@ -14,4 +14,4 @@ else %Well seems not to be overloaded => h = maingui.mywaitbarupdate(varargin{:}); -end; +end diff --git a/source/mywarning.m b/source/mywarning.m index 1e67bdb..a0b82eb 100644 --- a/source/mywarning.m +++ b/source/mywarning.m @@ -3,6 +3,10 @@ function mywarning(stri,fighandle) % User needs to click OK to discard message. % %See also MYWARNINGNOBLOCK +% +% If DATA.Silent then message is just displayed in the console +% and exectution continues as if user had pressed ok. +% %%%% If changing this file, please also change mywarning no block, since %%%% they should be identical except for the uiwait(h); line. @@ -10,6 +14,16 @@ function mywarning(stri,fighandle) %Einar Heiberg +%If silent then just write to log and return +try + if DATA.Silent + disp(sprintf('Warning: %s',stri)); %#ok + return; + end +catch + %Do nothing as if error then depends on DATA not initialised +end + stri = translation.dictionary(stri); try @@ -17,22 +31,57 @@ function mywarning(stri,fighandle) %Just print warning message in window if DoNotAsk mode. mydisp(dprintf('Warning:%s\n',stri)); return; - end; + end catch %#ok -end; +end keystroke = popfrombuffer('KeyStroke'); if isempty(keystroke) disp(dprintf('Warning:%s\n',stri)); - h = warndlg(stri,'Warning:'); - - %Adjust horisontally - if nargin>1 + h = warndlg(stri,dprintf('Warning:'),'invisible'); + + %set color + try + htext = findobj(h, 'Type', 'Text'); %find text control in dialog + set(htext,'Color',DATA.GUISettings.ForegroundColor,'FontSize',9,'Units','normalized'); + catch me + mydispexception(me) + end + + %set icon + setupicon(h); + + try + set(h,'Color',DATA.GUISettings.BackgroundColor); + kids = h.Children; + for i=1:length(kids) + try set(kids(i),'BackgroundColor',DATA.GUISettings.BackgroundColor);catch, end + try set(kids(i),'Color',DATA.GUISettings.BackgroundColor);catch, end + try set(kids(i),'ForegroundColor',DATA.GUISettings.ForegroundColor);catch, end + try set(kids(i),'FontSize',12);catch, end + try + kidstyle = kids(i).Style; + if strcmp(kidstyle,'pushbutton') + set(kids(i),'Units','normalized','FontSize',9) + end + catch + end + end + catch me + mydispexception(me) + end + if length(stri) > 40 + ps = get(h,'Position'); + set(h,'Position',[ps(1) ps(2) ps(3)*1.2 ps(4)]) + end + %Adjust horizontally + if nargin > 1 myadjust(h,fighandle); else myadjust(h); - end; + end + set(h,'visible','on'); flushlog; uiwait(h); %This is the only difference to mywarningnoblock. try @@ -40,7 +89,7 @@ function mywarning(stri,fighandle) macro_helper('switchorder'); %We need to store data in buffer before the callback catch %#ok %Ignore if failed, likely due to DATA is cleared or not present - end; + end else disp(dprintf('Warning:%s\n',stri)); if isequal(lower(keystroke),'ok') @@ -49,7 +98,7 @@ function mywarning(stri,fighandle) macro_helper('switchorder'); %We need to store data in buffer before the callback return; else - error(sprintf('Expected ''ok'' as keystroke, got %s',keystroke)); - end; -end; + error(sprintf('Expected ''ok'' as keystroke, got %s',keystroke)); %#ok + end +end flushlog; diff --git a/source/mywarningnoblock.m b/source/mywarningnoblock.m index c6cfcb4..84e515c 100644 --- a/source/mywarningnoblock.m +++ b/source/mywarningnoblock.m @@ -2,20 +2,23 @@ function mywarningnoblock(stri,fighandle) %MYWARNING(STRI,HANDLE) Displays a warning message % User needs to click OK to discard message. % -%See also MYWARNINGNOBLOCK +% If DATA.Silent then message is just displayed in the console +% and exectution continues as if user had pressed ok. +% +%See also MYWARNING global DATA %Einar Heiberg try - if DATA.Pref.DoNotAsk + if DATA.Pref.DoNotAsk || DATA.Silent %Just print warning message in window if DoNotAsk mode. mydisp(dprintf('Warning:%s\n',stri)); return; - end; + end catch %#ok -end; +end mydisp(dprintf('Warning:%s\n',stri)); h = warndlg(stri,'Warning:'); @@ -25,7 +28,7 @@ function mywarningnoblock(stri,fighandle) myadjust(h,fighandle); else myadjust(h); -end; +end %uiwait(h); %This is the only difference to mywarning. If changing %mywarning, please also update this file. diff --git a/source/myworkoff.m b/source/myworkoff.m index db8ad69..15567a7 100644 --- a/source/myworkoff.m +++ b/source/myworkoff.m @@ -1,4 +1,4 @@ -function myworkoff +function myworkoff(fignr) %MYWORKOFF Graphically show that calculation is % finished by restoring pointer. @@ -7,17 +7,22 @@ global DATA %resume last pointer +if nargin==0 + fignr = gcf; +end + if ~isempty(DATA) - set(gcf,'pointer',DATA.LastPointer); + set(fignr,'pointer',DATA.LastPointer); else + close(fignr) return; -end; +end if ~isempty(DATA) if isequal(DATA.LastPointer,'custom') set(DATA.imagefig,'pointer',DATA.LastPointer,... 'pointershapecdata',DATA.LastPointerShapeCData); - end; -end; + end +end flushlog; \ No newline at end of file diff --git a/source/myworkon.m b/source/myworkon.m index caf83b0..55c803d 100644 --- a/source/myworkon.m +++ b/source/myworkon.m @@ -1,5 +1,6 @@ -function myworkon +function myworkon(fignr) %MYWORKON Graphically indicate that Segment is +% MYWORKON(); % busy by showing watch pointer. %Einar Heiberg @@ -9,7 +10,11 @@ temp = get(DATA.imagefig,'pointer'); else return; -end; +end + +if nargin==0 + fignr = gcf; +end if isequal(temp,'watch') return; @@ -17,7 +22,7 @@ if ~isempty(DATA) DATA.LastPointer = temp; DATA.LastPointerShapeCData = get(DATA.imagefig,'pointershapecdata'); - end; - set(gcf,'pointer','watch'); -end; + end + set(fignr,'pointer','watch'); +end drawnow; \ No newline at end of file diff --git a/source/nanconv.m b/source/nanconv.m new file mode 100644 index 0000000..091d8b9 --- /dev/null +++ b/source/nanconv.m @@ -0,0 +1,99 @@ +function c = nanconv(a, k, varargin) +% NANCONV Convolution in 1D or 2D ignoring NaNs. +% C = NANCONV(A, K) convolves A and K, correcting for any NaN values +% in the input vector A. The result is the same size as A (as though you +% called 'conv' or 'conv2' with the 'same' shape). +% +% C = NANCONV(A, K, 'param1', 'param2', ...) specifies one or more of the following: +% 'edge' - Apply edge correction to the output. +% 'noedge' - Do not apply edge correction to the output (default). +% 'nanout' - The result C should have NaNs in the same places as A. +% 'nonanout' - The result C should have ignored NaNs removed (default). +% Even with this option, C will have NaN values where the +% number of consecutive NaNs is too large to ignore. +% '2d' - Treat the input vectors as 2D matrices (default). +% '1d' - Treat the input vectors as 1D vectors. +% This option only matters if 'a' or 'k' is a row vector, +% and the other is a column vector. Otherwise, this +% option has no effect. +% +% NANCONV works by running 'conv2' either two or three times. The first +% time is run on the original input signals A and K, except all the +% NaN values in A are replaced with zeros. The 'same' input argument is +% used so the output is the same size as A. The second convolution is +% done between a matrix the same size as A, except with zeros wherever +% there is a NaN value in A, and ones everywhere else. The output from +% the first convolution is normalized by the output from the second +% convolution. This corrects for missing (NaN) values in A, but it has +% the side effect of correcting for edge effects due to the assumption of +% zero padding during convolution. When the optional 'noedge' parameter +% is included, the convolution is run a third time, this time on a matrix +% of all ones the same size as A. The output from this third convolution +% is used to restore the edge effects. The 'noedge' parameter is enabled +% by default so that the output from 'nanconv' is identical to the output +% from 'conv2' when the input argument A has no NaN values. +% +% See also conv, conv2 +% +% AUTHOR: Benjamin Kraus (bkraus@bu.edu, ben@benkraus.com) +% Copyright (c) 2013, Benjamin Kraus +% $Id: nanconv.m 4861 2013-05-27 03:16:22Z bkraus $ +% Process input arguments +for arg = 1:nargin-2 + switch lower(varargin{arg}) + case 'edge'; edge = true; % Apply edge correction + case 'noedge'; edge = false; % Do not apply edge correction + case {'same','full','valid'}; shape = varargin{arg}; % Specify shape + case 'nanout'; nanout = true; % Include original NaNs in the output. + case 'nonanout'; nanout = false; % Do not include NaNs in the output. + case {'2d','is2d'}; is1D = false; % Treat the input as 2D + case {'1d','is1d'}; is1D = true; % Treat the input as 1D + end +end +% Apply default options when necessary. +if(exist('edge','var')~=1); edge = false; end +if(exist('nanout','var')~=1); nanout = false; end +if(exist('is1D','var')~=1); is1D = false; end +if(exist('shape','var')~=1); shape = 'same'; +elseif(~strcmp(shape,'same')) + error([mfilename ':NotImplemented'],'Shape ''%s'' not implemented',shape); +end +% Get the size of 'a' for use later. +sza = size(a); +% If 1D, then convert them both to columns. +% This modification only matters if 'a' or 'k' is a row vector, and the +% other is a column vector. Otherwise, this argument has no effect. +if(is1D); + if(~isvector(a) || ~isvector(k)) + error('MATLAB:conv:AorBNotVector','A and B must be vectors.'); + end + a = a(:); k = k(:); +end +% Flat function for comparison. +o = ones(size(a)); +% Flat function with NaNs for comparison. +on = ones(size(a)); +% Find all the NaNs in the input. +n = isnan(a); +% Replace NaNs with zero, both in 'a' and 'on'. +a(n) = 0; +on(n) = 0; +% Check that the filter does not have NaNs. +if(any(isnan(k))); + error([mfilename ':NaNinFilter'],'Filter (k) contains NaN values.'); +end +% Calculate what a 'flat' function looks like after convolution. +if(any(n(:)) || edge) + flat = conv2(on,k,shape); +else flat = o; +end +% The line above will automatically include a correction for edge effects, +% so remove that correction if the user does not want it. +if(any(n(:)) && ~edge); flat = flat./conv2(o,k,shape); end +% Do the actual convolution +c = conv2(a,k,shape)./flat; +% If requested, replace output values with NaNs corresponding to input. +if(nanout); c(n) = NaN; end +% If 1D, convert back to the original shape. +if(is1D && sza(1) == 1); c = c.'; end +end diff --git a/source/neldermeadsegmex2pMAGIR_convergence.mexw32 b/source/neldermeadsegmex2pMAGIR_convergence.mexw32 deleted file mode 100644 index 6821776..0000000 Binary files a/source/neldermeadsegmex2pMAGIR_convergence.mexw32 and /dev/null differ diff --git a/source/neldermeadsegmex2pPSIR_convergence.mexw32 b/source/neldermeadsegmex2pPSIR_convergence.mexw32 deleted file mode 100644 index 7020909..0000000 Binary files a/source/neldermeadsegmex2pPSIR_convergence.mexw32 and /dev/null differ diff --git a/source/neldermeadsegmex2pSR_convergence.mexw32 b/source/neldermeadsegmex2pSR_convergence.mexw32 deleted file mode 100644 index 1499428..0000000 Binary files a/source/neldermeadsegmex2pSR_convergence.mexw32 and /dev/null differ diff --git a/source/neldermeadsegmex2pT2_convergence.mexw32 b/source/neldermeadsegmex2pT2_convergence.mexw32 deleted file mode 100644 index cc39ff2..0000000 Binary files a/source/neldermeadsegmex2pT2_convergence.mexw32 and /dev/null differ diff --git a/source/neldermeadsegmex3pMAGIR_convergence.mexw32 b/source/neldermeadsegmex3pMAGIR_convergence.mexw32 deleted file mode 100644 index 03e2ba5..0000000 Binary files a/source/neldermeadsegmex3pMAGIR_convergence.mexw32 and /dev/null differ diff --git a/source/neldermeadsegmex3pPSIR_convergence.mexw32 b/source/neldermeadsegmex3pPSIR_convergence.mexw32 deleted file mode 100644 index 8fb1742..0000000 Binary files a/source/neldermeadsegmex3pPSIR_convergence.mexw32 and /dev/null differ diff --git a/source/neldermeadsegmex3pT2_convergence.mexw32 b/source/neldermeadsegmex3pT2_convergence.mexw32 deleted file mode 100644 index 363e206..0000000 Binary files a/source/neldermeadsegmex3pT2_convergence.mexw32 and /dev/null differ diff --git a/source/newfindedges.mexw32 b/source/newfindedges.mexw32 deleted file mode 100644 index 1636aee..0000000 Binary files a/source/newfindedges.mexw32 and /dev/null differ diff --git a/source/newicons.mat b/source/newicons.mat index 04b3db8..6c40562 100644 Binary files a/source/newicons.mat and b/source/newicons.mat differ diff --git a/source/nv/1269.nv b/source/nv/1269.nv new file mode 100644 index 0000000..4ef1d98 Binary files /dev/null and b/source/nv/1269.nv differ diff --git a/source/nv/8147.nv b/source/nv/8147.nv new file mode 100644 index 0000000..7b6bb0e Binary files /dev/null and b/source/nv/8147.nv differ diff --git a/source/nv/9057.nv b/source/nv/9057.nv new file mode 100644 index 0000000..f35d436 Binary files /dev/null and b/source/nv/9057.nv differ diff --git a/source/nv/9133.nv b/source/nv/9133.nv new file mode 100644 index 0000000..d8c0a71 Binary files /dev/null and b/source/nv/9133.nv differ diff --git a/source/nvload.p b/source/nvload.p new file mode 100644 index 0000000..a17f6a8 Binary files /dev/null and b/source/nvload.p differ diff --git a/source/nvprocess.p b/source/nvprocess.p new file mode 100644 index 0000000..7998960 Binary files /dev/null and b/source/nvprocess.p differ diff --git a/source/oflog.dll b/source/oflog.dll new file mode 100644 index 0000000..0d5d72a Binary files /dev/null and b/source/oflog.dll differ diff --git a/source/ofstd.dll b/source/ofstd.dll new file mode 100644 index 0000000..b92da0a Binary files /dev/null and b/source/ofstd.dll differ diff --git a/source/oldfastlevelset.mexw32 b/source/oldfastlevelset.mexw32 deleted file mode 100644 index 068aae9..0000000 Binary files a/source/oldfastlevelset.mexw32 and /dev/null differ diff --git a/source/openfile.fig b/source/openfile.fig index 58a3b9b..3c362b7 100644 Binary files a/source/openfile.fig and b/source/openfile.fig differ diff --git a/source/openfile.p b/source/openfile.p index a4163ee..d54a781 100644 Binary files a/source/openfile.p and b/source/openfile.p differ diff --git a/source/pacs.p b/source/pacs.p deleted file mode 100644 index f37ca49..0000000 Binary files a/source/pacs.p and /dev/null differ diff --git a/source/pacsaccess.fig b/source/pacsaccess.fig new file mode 100644 index 0000000..ab80e99 Binary files /dev/null and b/source/pacsaccess.fig differ diff --git a/source/pacsaccess.p b/source/pacsaccess.p new file mode 100644 index 0000000..aed5a78 Binary files /dev/null and b/source/pacsaccess.p differ diff --git a/source/pacscon.fig b/source/pacscon.fig deleted file mode 100644 index cbba291..0000000 Binary files a/source/pacscon.fig and /dev/null differ diff --git a/source/pacspref.fig b/source/pacspref.fig index ab1eca5..fcc4743 100644 Binary files a/source/pacspref.fig and b/source/pacspref.fig differ diff --git a/source/pacspref.m b/source/pacspref.m index b133da0..b4a1508 100644 --- a/source/pacspref.m +++ b/source/pacspref.m @@ -28,14 +28,12 @@ %Initiate Pacs Preferences GUI global DATA -fig = openfig('pacspref.fig','reuse'); -translation.translatealllabels(fig); -set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); +fig = mygui('pacspref.fig'); % Generate a structure of handles to pass to callbacks -handles = guihandles(fig); +handles = fig.handles; DATA.PrefHandlesPacs = handles; -DATA.PrefHandlesPacs.fig = fig; +DATA.PrefHandlesPacs.fig = handles.figure1; patientkids = get(handles.patientlevelpanel,'Children'); studykids = get(handles.studylevelpanel,'Children'); @@ -128,7 +126,7 @@ for loop=1:length(f) load(f(loop).name,'res','-mat'); li{loop} = res.DescriptiveName; -end; +end % update v v = mygetlistbox(DATA.PrefHandlesPacs.connecttolistbox); @@ -252,18 +250,42 @@ function queryconfig_Callback(level) global DATA % Ask user for input -s.Descriptive_Name = 'name'; %DescriptiveName -s.PACS_AE_Title = 'HOSPITAL_PACS' ; %Called_AE -s.PACS_IP_Number = '127.0.0.1'; %Peer_IP -s.PACS_Port_Number = '4006'; %Peer_Port -s.Segment_Port_Number = '104'; %Port -s.Retrieve_AE_Title = DATA.Pref.Server.AETitle; %Take from Segment Server AE Title -s.Query_AE_Title = DATA.Pref.Server.AETitle; %Take from Segment Server AE Title -s.StoreSCU_AE_Title = DATA.Pref.Server.AETitle; %Take from Segment Server AE Title -[res,ok] = inputstruct(s,'Input connection details.'); +s = []; +s(1).Field = 'Descriptive_Name'; +s(1).Label = dprintf('Descriptive Name'); +s(1).Default = 'Name '; +n = 2; +s(n).Field = 'PACS_AE_Title'; +s(n).Label = dprintf('PACS AE Title'); +s(n).Default = 'HOSPITAL_PACS'; %Called_AE +n = n+1; +s(n).Field = 'PACS_IP_Number'; +s(n).Label = dprintf('PACS IP Number'); +s(n).Default = '127.0.0.1'; %Peer_IP +n = n+1; +s(n).Field = 'PACS_Port_Number'; +s(n).Label = dprintf('PACS Port Number'); +s(n).Default = '4006'; %Peer_Port +n = n+1; +s(n).Field = 'Segment_Port_Number'; +s(n).Label = dprintf('Segment Port Number'); +s(n).Default = '104'; %Port +n = n+1; +s(n).Field = 'Retrieve_AE_Title'; +s(n).Label = dprintf('Retrieve AE Title'); +s(n).Default = DATA.Pref.Server.AETitle; %Take from Segment Server AE Title +n = n+1; +s(n).Field = 'Query_AE_Title'; +s(n).Label = dprintf('Query AE Title'); +s(n).Default = DATA.Pref.Server.AETitle; %Take from Segment Server AE Title +n = n+1; +s(n).Field = 'StoreSCU_AE_Title'; +s(n).Label = dprintf('StoreSCU AE Title'); +s(n).Default = DATA.Pref.Server.AETitle; %Take from Segment Server AE Title +[res,ok] = myinputstruct(s,'',20); %20 = width of editbox if not(ok) return; -end; +end temp = res; s = []; @@ -278,10 +300,14 @@ function queryconfig_Callback(level) clear temp; % Store the con file -[filename,pathname] = myuiputfile('*.con','Save Connection As: (place in Segment folder)'); -if isequal(filename,0)||isequal(pathname,0) - return; -end; +% [filename,pathname] = myuiputfile('*.con','Save Connection As: (place in Segment folder)'); +% if isequal(filename,0)||isequal(pathname,0) +% return; +% end + +%The .con file is saved in main software folder as DescriptiveName.con +filename=[s.DescriptiveName '.con']; +pathname=DATA.SegmentFolder; res = s; res.Calling_AE = 'DEFAULT_CALLING_AE'; % Added for legacy reasons save(fullfile(pathname,filename),'res', DATA.Pref.SaveVersion); @@ -303,40 +329,77 @@ function queryconfig_Callback(level) try load(f(v).name, 'res', '-mat'); catch e - myfailed(dprintf(... - 'Could not open the selected connection. Error is ''%s''',e.message),DATA.GUI.PacsCon); + myfailed(dprintf('Could not open the selected connection. Error is ''%s''',e.message),DATA.GUI.PacsCon); updatepacscon; return end %Remove non used field from display -res = rmfield(res, 'Calling_AE'); %#ok +res = rmfield(res, 'Calling_AE'); %Prepare variable with new fieldnames s = []; -s.Descriptive_Name = res.DescriptiveName; -s.PACS_AE_Title = res.Called_AE; -s.PACS_IP_Number = res.Peer_IP; -s.PACS_Port_Number = res.Peer_Port; -s.Segment_Port_Number = res.Port; +n = 1; +s(n).Field = 'Descriptive_Name'; +s(n).Label = dprintf('Descriptive Name'); +s(n).Default = res.DescriptiveName; +n = n+1; +s(n).Field = 'PACS_AE_Title'; +s(n).Label = dprintf('PACS AE Title'); +s(n).Default = res.Called_AE; +n = n+1; +s(n).Field = 'PACS_IP_Number'; +s(n).Label = dprintf('PACS IP Number'); +s(n).Default = res.Peer_IP; +n = n+1; +s(n).Field = 'PACS_Port_Number'; +s(n).Label = dprintf('PACS Port Number'); +s(n).Default = res.Peer_Port; +n = n+1; +s(n).Field = 'Segment_Port_Number'; +s(n).Label = dprintf('Segment Port Number'); +s(n).Default = res.Port; +n = n+1; if isfield(res,'Retrieve_AE_Title') - s.Retrieve_AE_Title = res.Retrieve_AE_Title; -else - s.Retrieve_AE_Title = DATA.Pref.Server.AETitle; %Take from Segment Server AETitle -end; + s(n).Field = 'Retrieve_AE_Title'; + s(n).Label = dprintf('Retrieve AE Title'); + s(n).Default = res.Retrieve_AE_Title; + n = n+1; +else + s(n).Field = 'Retrieve_AE_Title'; + s(n).Label = dprintf('Retrieve AE Title'); + s(n).Default = DATA.Pref.Server.AETitle; %Take from Segment Server AETitle + n = n+1; +end if isfield(res,'Query_AE_Title') - s.Query_AE_Title = res.Query_AE_Title; + s(n).Field = 'Query_AE_Title'; + s(n).Label = dprintf('Query AE Title'); + s(n).Default = res.Query_AE_Title; + n = n+1; else - s.Query_AE_Title = DATA.Pref.Server.AETitle; %Take from Segment Server AETitle -end; + s(n).Field = 'Query_AE_Title'; + s(n).Label = dprintf('Query AE Title'); + s(n).Default = DATA.Pref.Server.AETitle; %Take from Segment Server AETitle + n = n+1; +end if isfield(res,'StoreSCU_AE_Title') - s.StoreSCU_AE_Title = res.StoreSCU_AE_Title; -else - s.StoreSCU_AE_Title = DATA.Pref.Server.AETitle; %Take from Segment Server AETitle -end; + s(n).Field = 'StoreSCU_AE_Title'; + s(n).Label = dprintf('StoreSCU AE Title'); + s(n).Default = res.StoreSCU_AE_Title; + n = n+1; %#ok +else + s(n).Field = 'StoreSCU_AE_Title'; + s(n).Label = dprintf('StoreSCU AE Title'); + s(n).Default = DATA.Pref.Server.AETitle; %Take from Segment Server AETitle + n = n+1; %#ok +end % Let user edit the file and save it -[s,ok] = inputstruct(s); +[s,ok] = myinputstruct(s,'',20); %20 is width of editboxes + +if not(ok) + return; +end %Convert to internal fieldname representation temp = s; @@ -352,15 +415,13 @@ function queryconfig_Callback(level) clear temp; res.Calling_AE = 'DEFAULT_CALLING_AE'; -if not(ok) - return; -end; + try save(f(v).name, 'res', DATA.Pref.SaveVersion); catch myfailed('Could not save connection file. Disk write protected?'); -end; +end %Update the list updatepacscon; @@ -381,7 +442,7 @@ function queryconfig_Callback(level) myfailed(errormsg,DATA.GUI.PacsCon); updatepacscon; return; -end; +end ok = mydel(f(v).name); if not(ok) errormsg=sprintf(... @@ -389,14 +450,14 @@ function queryconfig_Callback(level) f(v).name, w); myfailed(errormsg,DATA.GUI.PacsCon); return; -end; +end % Update listbox value and updates pacscon if length(f)>1 set(DATA.PrefHandlesPacs.connecttolistbox, 'value', 1); else set(DATA.PrefHandlesPacs.connecttolistbox, 'value', 0); -end; +end updatepacscon; %------------------------ @@ -413,13 +474,13 @@ function queryconfig_Callback(level) DATA.Pref.Pacs.VerboseLog=0; DATA.Pref.Pacs.DebugLog=0; -DATA.Pref.Pacs.patientconfig = [1 0 1 1 0 0]; -DATA.Pref.Pacs.studyconfig = [0 0 1 1 1 0 1 1 1 1 0 0 1]; -DATA.Pref.Pacs.seriesconfig = [0 0 1 0 1 1 1 1 1 1 0 0 0]; +DATA.Pref.Pacs.patientconfig = [0 1 1 1 0 0]; +DATA.Pref.Pacs.studyconfig = [0 1 0 1 1 0 1 1 1 1 1 1 0]; +DATA.Pref.Pacs.seriesconfig = [0 1 0 1 1 1 1 1 1 1 1 1 0]; DATA.Pref.Pacs.QueryOptions = ''; %'--propose-little'; -DATA.Pref.Pacs.retrievemodel = [1 0 0]; -DATA.Pref.Pacs.RetrieveMode=2; +DATA.Pref.Pacs.retrievemodel = [0 1 0]; +DATA.Pref.Pacs.RetrieveMode=4; DATA.Pref.Pacs.RetrieveOptions = ''; %'--prefer-little --propose-little --bit-preserving'; %--------------------- diff --git a/source/papillaryslider.fig b/source/papillaryslider.fig index cbbbfc3..4a1262b 100644 Binary files a/source/papillaryslider.fig and b/source/papillaryslider.fig differ diff --git a/source/papillaryslider.m b/source/papillaryslider.m index 772d1ad..9a5e8fd 100644 --- a/source/papillaryslider.m +++ b/source/papillaryslider.m @@ -5,7 +5,7 @@ function papillaryslider(arg) if nargin == 0 arg = 'init'; -end; +end switch arg case 'init' @@ -15,16 +15,27 @@ function papillaryslider(arg) try gui = DATA.GUI.PapillarySlider; + %This solution does not seem to work + %warning off + %jFig = get(DATA.fig,'JavaFrame'); + %jFig.requestFocus; + %warning on + v = get(gui.handles.papillarythresholdslider,'value'); - SET(NO).PapillaryThreshold = v; - + if isapproxequal(abs(SET(NO).PapillaryThreshold-v),0.0082) + v = SET(NO).PapillaryThreshold; + set(gui.handles.papillarythresholdslider,'value',v); + else + SET(NO).PapillaryThreshold = v; + end + if ~isempty(SET(NO).EndoX) lvpeter('segmentestimatepapilaryvolume_Callback'); figure(gui.fig); - end; + end catch me mydispexception(me); - end; + end case 'close' try DATA.GUI.PapillarySlider = close(DATA.GUI.PapillarySlider); @@ -32,5 +43,5 @@ function papillaryslider(arg) delete(gcbf); DATA.GUI.PapillarySlider = []; end -end; +end diff --git a/source/patientdatabase.fig b/source/patientdatabase.fig index ef374db..86a8912 100644 Binary files a/source/patientdatabase.fig and b/source/patientdatabase.fig differ diff --git a/source/patientdatabase.p b/source/patientdatabase.p index 964f356..32ec5af 100644 Binary files a/source/patientdatabase.p and b/source/patientdatabase.p differ diff --git a/source/patientdatabaseaddstudyhelper.p b/source/patientdatabaseaddstudyhelper.p index 6ec163b..0195251 100644 Binary files a/source/patientdatabaseaddstudyhelper.p and b/source/patientdatabaseaddstudyhelper.p differ diff --git a/source/patientinfo.fig b/source/patientinfo.fig index c01d7c1..75e0053 100644 Binary files a/source/patientinfo.fig and b/source/patientinfo.fig differ diff --git a/source/perfusion.m b/source/perfusion.m index 3a806de..28b1009 100644 --- a/source/perfusion.m +++ b/source/perfusion.m @@ -49,12 +49,12 @@ function createmyocardmask(no) if isempty(SET(no).Perfusion) initdefault(no); -end; +end if isempty(SET(no).EndoX) myfailed('No LV endocardium available.'); return; -end; +end %Create mask, allways update, segmentation could have changed. SET(no).Perfusion.MyocardMask = false([SET(no).XSize SET(no).YSize SET(no).TSize SET(no).ZSize]); @@ -82,10 +82,10 @@ function createmyocardmask(no) manualtemp(~mask)=int8(0); SET(no).Perfusion.Manual(:,:,tloop,slicetomask(zloop)) = manualtemp; end -end; +end %----------------------- -function calcvolume(no) %#ok +function calcvolume(no) %----------------------- global SET NO @@ -107,7 +107,7 @@ function showmanualinteraction_Callback(arg) if nargin==0 arg = 'toggle'; -end; +end switch arg case 'toggle' @@ -116,7 +116,7 @@ function showmanualinteraction_Callback(arg) set(DATA.Handles.Perfusionshowmanualinteractionmenu,'checked','off'); else set(DATA.Handles.Perfusionshowmanualinteractionmenu,'checked','on'); - end; + end case 'on' set(DATA.Handles.Perfusionshowmanualinteractionmenu,'checked','off'); case 'off' @@ -125,7 +125,7 @@ function showmanualinteraction_Callback(arg) %Do nothing otherwise error('Invalid option to showmanualinteraction_Callback, should not occur.'); -end; +end %Update c = get(DATA.Handles.Perfusionshowmanualinteractionmenu,'checked'); @@ -134,7 +134,7 @@ function showmanualinteraction_Callback(arg) segment('unlighttool',DATA.Tools.Perfusionhide); else segment('highlighttool',DATA.Tools.Perfusionhide); -end; +end update; @@ -148,7 +148,7 @@ function showmanualinteraction_Callback(arg) update; segment('updatevolume'); -drawfunctions('drawimageno'); +viewfunctions('setview'); %drawfunctions('drawimageno'); %-------------- function update(no,silent) @@ -174,8 +174,8 @@ function update(no,silent) segment('updatevolume'); if isequal(SET(no).Perfusion.Mode,'manual')&¬(silent) - drawfunctions('drawimageno'); %Make sure graphically updated when manual mode. - end; + viewfunctions('setview'); %drawfunctions('drawimageno'); + end end %--------------------------------------------------- @@ -186,19 +186,19 @@ function update(no,silent) if isempty(SET(no).Perfusion) initdefault; -end; +end if nargin<1 error('Expected one input argument to getPerfusionmask.'); -end; +end if nargin<2 timeframe = SET(no).CurrentTimeFrame; -end; +end if nargin<3 slice = SET(no).CurrentSlice; -end; +end mask = SET(no).Perfusion.Result(:,:,timeframe,slice); @@ -219,7 +219,7 @@ function drawhelper(no,panel) result = SET(no).Perfusion.Result(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); otherwise myfailed('Unknown viewtype in Perfusion-drawhelper.'); -end; +end if (sum(result(:))>0) @@ -233,10 +233,10 @@ function drawhelper(no,panel) set(DATA.Handles.Perfusioncontour{panel},'linewidth',DATA.Pref.LineWidth); else set(DATA.Handles.Perfusioncontour{panel},'visible','off'); - end; + end else DATA.Handles.Perfusioncontour{panel} = []; -end; +end %--------------------- function showedits(no) @@ -246,22 +246,22 @@ function showedits(no) if nargin==0 no = NO; -end; +end if isempty(SET(no).Perfusion) return; -end; +end %Check if menu is enabled if isequal(get(DATA.Handles.hideoverlayicon,'state'),'on') manualinteraction = false; else manualinteraction = true; -end; +end if not(manualinteraction) return; -end; +end tempnos=no; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -273,7 +273,7 @@ function showedits(no) panelstodo = find(DATA.ViewPanels==no); else panelstodo = DATA.CurrentPanel; -end; +end for panel=panelstodo @@ -283,7 +283,7 @@ function showedits(no) isrgbimage = true; else isrgbimage = false; - end; + end clear temp; @@ -297,7 +297,7 @@ function showedits(no) else %Default grayscale image tempuint8 = min(uint8(255),uint8(1)+calcfunctions('remapuint8',temp)); tempuint8 = repmat(tempuint8,[1 1 3]); %EH: - end; + end clear temp; sz=size(tempuint8); Perfusionimrgb = reshape(tempuint8,[prod(sz(1:2)) 3]); @@ -343,7 +343,7 @@ function showedits(no) if isempty(SET(no).Scar) myfailed('No Scar to import from.'); -end; +end if isempty(SET(no).Perfusion) initdefault; @@ -372,7 +372,7 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if nargin==0 %Find what imagestack - s = inputdlg({'Enter what image stack to take from '},'ImageStack',1,{sprintf('%d',1)}); + s = myinputdlg({'Enter what image stack to take from '},'ImageStack',1,{sprintf('%d',1)}); if isempty(s) myfailed('Invalid image stack.',DATA.GUI.Segment); @@ -382,18 +382,18 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if not(ok) myfailed('Invalid image stack.',DATA.GUI.Segment); return; - end; - end; -end; + end + end +end if fromno==no myfailed('Cannot import from same image stack.',DATA.GUI.Segment); return; -end; +end if (fromno>length(SET))||(fromno<1) myfailed('Invalid image stack selected.',DATA.GUI.Segment); return; -end; +end if isempty(SET(fromno).Perfusion) myfailed('Perfusion must be present in image stack to import form'); @@ -422,7 +422,7 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if isempty(SET(no).Perfusion) myfailed('No Perfusion to export from.'); -end; +end if SET(NO).TSize>1 myfailed('Can only exprot to Scar when Perfusion is non-timeresolved.'); @@ -446,7 +446,7 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if isempty(SET(NO).Perfusion) initdefault; -end; +end tools('enableundo'); %Clear manual interaction @@ -471,7 +471,7 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if nargin<2 no = NO; -end; +end pos = SET(no).StartSlice:SET(no).EndSlice; numslices = length(pos); @@ -481,16 +481,16 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if isempty(SET(no).Perfusion) myfailed('No Perfusion data available.',DATA.GUI.Segment); return; -end; +end if isempty(SET(no).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end if isempty(SET(no).EpiX) myfailed('No LV epicardium available.',DATA.GUI.Segment); return; -end; +end %Upsample model if not(DATA.Pref.RadialProfiles==DATA.NumPoints) @@ -501,7 +501,7 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) endoy = SET(no).EndoY; epix = SET(no).EpiX; epiy = SET(no).EpiY; -end; +end maxtrans = zeros(numsectors,numslices); transmurality = zeros(DATA.Pref.RadialProfiles,1,SET(no).ZSize); @@ -545,8 +545,8 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) if length(sectorind)>2 sectorendind(indepi,1,pos(sloop)) = (sectorind(end)-1)/49; sectorstartind(indepi,1,pos(sloop)) = (sectorind(1)-1)/49; - end; - end; %loop over datapoints + end + end %loop over datapoints tempres = calcfunctions('findmeaninsector','epi',transmurality,pos(sloop),numsectors,no); % [res(:,sloop),tempa,tempa,tempa,maxtrans(:,sloop)] = res(:,sloop) = tempres(:,tf); tempres = calcfunctions('findmeaninsector','epi',sectorendind,pos(sloop),numsectors,no); @@ -565,16 +565,16 @@ function importfromimagestackwithdifferentcrop_Callback(fromno) varargout = cell(nargout-1,1); if nargout>1 varargout{1} = maxtrans; -end; +end if nargout>2 varargout{2} = meantrans4infarct; -end; +end if nargout>3 varargout{3} = totextent; -end; +end if nargout>4 varargout{4} = startind; -end; +end if nargout>5 varargout{5} = endind; end diff --git a/source/phantoms.m b/source/phantoms.m index 314b698..0c2844c 100644 --- a/source/phantoms.m +++ b/source/phantoms.m @@ -33,7 +33,7 @@ DATA.Preview.TSize = size(SET(NO).IM,3); DATA.Preview.ZSize = size(SET(NO).IM,4); DATA.Preview.TIncr = 1; -DATA.Preview.TimeVector = 0:1:size(SET(NO).IM,3)-1; +DATA.Preview.TimeVector = 0:1:size(SET(NO).IM,3)-1; DATA.Preview.Bitstored = 12; DATA.Preview.TriggerTime = DATA.Preview.TimeVector; @@ -97,12 +97,12 @@ coordinatephantom; otherwise mywarning('Aborted by user.',DATA.GUI.Segment); -end; +end %---------------- function phantom1 %---------------- -global SET NO +global DATA SET NO %phantom1 nx = 64; @@ -114,7 +114,7 @@ SET(NO).IM = repmat(single(0),[nx ny nt nz]); for loop=1:size(SET(NO).IM,3) SET(NO).IM(:,:,loop,:) = repmat(single(sqrt((x-nx/2).^2+(y-ny/2).^2)<4*sqrt(loop)),[1 1 1 nz]); -end; +end SET(NO).IM(:,34,:,:) = 1-SET(NO).IM(:,34,:,:); SET(NO).CenterX = nx/2; @@ -126,6 +126,11 @@ openfile('setupstacksfromdicom',NO); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %----------------------------- function cylinder(inrad,outrad) %----------------------------- @@ -135,7 +140,7 @@ function cylinder(inrad,outrad) if nargin==0 %ask inner radius - s = inputdlg({'Enter inner radius (endocard)'},'InnerRadius',1,{sprintf('%d',30)}); + s = myinputdlg({'Enter inner radius (endocard)'},'InnerRadius',1,{sprintf('%d',30)}); if isempty(s) myfailed('Invalid inner radius.',DATA.GUI.Segment); return; @@ -144,10 +149,10 @@ function cylinder(inrad,outrad) if not(ok) myfailed('Invalid inner radius.',DATA.GUI.Segment); return; - end; - end; + end + end %ask outer radius - s = inputdlg({'Enter outer radius (epicard)'},'OuterRadius',1,{sprintf('%d',50)}); + s = myinputdlg({'Enter outer radius (epicard)'},'OuterRadius',1,{sprintf('%d',50)}); if isempty(s) myfailed('Invalid outer radius.',DATA.GUI.Segment); return; @@ -156,9 +161,9 @@ function cylinder(inrad,outrad) if not(ok) myfailed('Invalid outer radius.',DATA.GUI.Segment); return; - end; - end; -end; + end + end +end nx = 128; ny = 128; @@ -177,20 +182,38 @@ function cylinder(inrad,outrad) openfile('setupstacksfromdicom',NO); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %---------------- function phantom3 %---------------- -global SET NO +global DATA SET NO +%Initialize image nx = 256; x = ndgrid(1:nx,1:nx); + +%Find which is the next position in SET structu NO = length(SET)+1; -SET(NO).IM = single(x)/nx; + +%Assign image +SET(NO).IM = single(x)/nx; %x, y , t, z + +%Call helper function to setup DATA variable correctly filephantomhelper; +%Code for setting up the SET struct openfile('setupstacksfromdicom',NO); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %---------------- function phantom4 %---------------- @@ -201,9 +224,9 @@ function cylinder(inrad,outrad) NO = length(SET)+1; im = single(zeros(nx,ny)); im = repmat(im,[1 1 1 10]); -for loop=1:10; +for loop=1:10 im((loop):(loop+10),40:60,1,loop) = 1; -end; +end SET(NO).IM = single(im); filephantomhelper; DATA.Preview.ResolutionX = 1; @@ -212,6 +235,11 @@ function cylinder(inrad,outrad) openfile('setupstacksfromdicom',NO); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %---------------------------- function im = helpfilter(im,n) %---------------------------- @@ -306,7 +334,7 @@ function cylinder(inrad,outrad) %Apply mask for loop = 1:size(im,4) im(:,:,loop) = im(:,:,loop).*single(mask); -end; +end %Store image SET(NO).IM = single(im); @@ -348,12 +376,14 @@ function cylinder(inrad,outrad) l = cell(1,nz); for loop = 1:nz l{loop} = sprintf('%0.3g',fullindex(loop)); -end; +end SET(NO).Point.Label = l; -segment('makeviewim'); -drawfunctions('drawall'); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawno',NO) +% segment('makeviewim'); +% drawfunctions('drawall'); %----------------------------------- function plaincylinder(inrad,outrad) @@ -364,7 +394,7 @@ function plaincylinder(inrad,outrad) if nargin==0 %ask inner radius - s = inputdlg({'Enter inner radius (endocard)'},'InnerRadius',1,{sprintf('%d',20)}); + s = myinputdlg({'Enter inner radius (endocard)'},'InnerRadius',1,{sprintf('%d',20)}); if isempty(s) myfailed('Invalid inner radius.',DATA.GUI.Segment); return; @@ -373,10 +403,10 @@ function plaincylinder(inrad,outrad) if not(ok) myfailed('Invalid inner radius.',DATA.GUI.Segment); return; - end; - end; + end + end %ask outer radius - s = inputdlg({'Enter outer radius (epicard)'},'OuterRadius',1,{sprintf('%d',30)}); + s = myinputdlg({'Enter outer radius (epicard)'},'OuterRadius',1,{sprintf('%d',30)}); if isempty(s) myfailed('Invalid outer radius.',DATA.GUI.Segment); return; @@ -385,9 +415,9 @@ function plaincylinder(inrad,outrad) if not(ok) myfailed('Invalid outer radius.',DATA.GUI.Segment); return; - end; - end; -end; + end + end +end nx = 100; ny = 100; @@ -405,6 +435,11 @@ function plaincylinder(inrad,outrad) SET(NO).TIncr = 1; segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------- function torus %------------- @@ -439,10 +474,15 @@ function plaincylinder(inrad,outrad) sprintf('Innerradius=10, Outerradius=15, Radius of torso (center)=30, volume=%0.5g ml',... volume),'',DATA.GUI.Segment); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %----------------- function qflowtest %----------------- -global SET NO +global DATA SET NO %Qflow test nx = 64; @@ -473,7 +513,7 @@ function plaincylinder(inrad,outrad) phase = mag; for tloop=1:nt phase(:,:,tloop,:) = (mag(:,:,tloop,:)>0.3)*t(tloop)+0.5; -end; +end log = (mag<0.3); phase(log) = 1; @@ -510,6 +550,11 @@ function plaincylinder(inrad,outrad) segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------------------ function yi = upsamplehelper(y,n) %------------------------------ @@ -554,7 +599,7 @@ function pwhelper(rad,flow,roiname) %---------------------------------- %Helper function to add image stacks -global SET NO +global DATA SET NO nx = 256; ny = 256; @@ -586,17 +631,17 @@ function pwhelper(rad,flow,roiname) if max(phasevalue)>1 error('Wrapping.'); -end; +end if max(phasevalue)<0 error('Wrapping.'); -end; +end %Phase image phase = mag; for tloop=1:nt phase(:,:,tloop,:) = phasevalue(tloop)*mag(:,:,tloop,:); -end; +end phase(phase==0) = 0.5; phase(1) = 0; %Ensure normalization @@ -655,7 +700,11 @@ function pwhelper(rad,flow,roiname) SET(phaseno).TimeVector = linspace(0,1,nt); SET(phaseno).TIncr = SET(phaseno).TimeVector(2)-SET(phaseno).TimeVector(1); - +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %--------------- function pwvtest %--------------- @@ -736,10 +785,10 @@ function pwhelper(rad,flow,roiname) subplot(2,1,2); plot(imp); pause; - end; + end tmeas(tloop) = pwtestcalchelper(aorticflow,abdominalflow); - end; + end truevel = aorticlength./ttrue; measvel = aorticlength./tmeas; @@ -755,7 +804,7 @@ function pwhelper(rad,flow,roiname) if loop==16 1 - end; + end disp(sprintf('%d timeframes: %0.5g+-%0.5g',points(loop),mean(truevel-measvel),std(truevel-measvel))); @@ -774,9 +823,9 @@ function pwhelper(rad,flow,roiname) h = ylabel('Measured pulse wave velocity [m/s]'); set(h,'fontsize',fs); h = title(dprintf('Derived from %d timeframes',points(loop))); set(h,'fontsize',fs); set(69+loop,'color',[1 1 1]); - end; + end -end; +end figure(190); h = plot(points,errorpercent20,'r-');set(h,'linewidth',2); set(h,'markersize',6); @@ -804,7 +853,7 @@ function pwhelper(rad,flow,roiname) outdata{loop-19,7} = errorpercent14(loop-19); outdata{loop-19,8} = errorpercent10(loop-19); outdata{loop-19,9} = errorpercent4(loop-19); -end; +end segment('cell2clipboard',outdata); @@ -845,7 +894,7 @@ function pwhelper(rad,flow,roiname) flowcurve = flow1; else flowcurve = flow2; - end; + end timevec = linspace(0,1000,length(flow1)); tmax = max(tmax,timevec(end)); @@ -873,7 +922,7 @@ function pwhelper(rad,flow,roiname) %----------------- function flow3test %----------------- -global SET NO +global DATA SET NO %3D flow test nx = 64; @@ -903,7 +952,7 @@ function pwhelper(rad,flow,roiname) phase = mag; for tloop=1:nt phase(:,:,tloop,:) = (mag(:,:,tloop,:)>0.3)*t(tloop)+0.5; -end; +end log = find((mag<0.3)); phase(log) = 1; phase(log) = phase(log).*rand(size(log)); @@ -941,6 +990,11 @@ function pwhelper(rad,flow,roiname) segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------- function straintest1 %------------------- @@ -971,7 +1025,7 @@ function pwhelper(rad,flow,roiname) v = 0.5-0.5*single(sin(2*pi*(0:(nt-1))/nt)); for loop=1:nt SET(2).IM(:,:,loop,1) = v(loop); -end; +end phasenox = 2; NO = 2; filephantomhelper; @@ -1022,6 +1076,11 @@ function pwhelper(rad,flow,roiname) segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------- function straintest2 %------------------- @@ -1074,7 +1133,7 @@ function pwhelper(rad,flow,roiname) SET(1).IM = repmat(single(0),[nx ny nt nz]); for tloop=1:nt SET(1).IM(16:round(48-pos(tloop)),16:48,tloop) = 1; -end; +end NO = 1; magno = NO; @@ -1101,7 +1160,7 @@ function pwhelper(rad,flow,roiname) sweep = sweep(:); %Reshape it. SET(2).IM(:,16:48,tloop) = repmat(sweep,[1 33]); %Store into the matrix. -end; +end max(SET(2).IM(:)) min(SET(2).IM(:)) @@ -1165,9 +1224,16 @@ function pwhelper(rad,flow,roiname) SET(phasenox).TIncr = tincr; SET(phasenoy).TIncr = tincr; -drawfunctions('drawall'); +% drawfunctions('drawall'); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + +viewfunctions('setview'); + %----------------------------- function t2starphantom(noisef) %----------------------------- @@ -1175,7 +1241,7 @@ function t2starphantom(noisef) if nargin==0 noisef = 0.01; -end; +end nx = 100; ny = nx; @@ -1201,8 +1267,8 @@ function t2starphantom(noisef) for yloop=1:10 t2map((1+(xloop-1)*10):(xloop*10),(1+(yloop-1)*10):(yloop*10)) = t2(pos); pos = pos+1; - end; -end; + end +end r2map = 1./t2map; @@ -1214,9 +1280,9 @@ function t2starphantom(noisef) for xloop=1:nx for yloop=1:ny SET(NO).IM(xloop,yloop,tloop) = single(exp(-r2map(xloop,yloop)*echotimes(tloop))); - end; - end; -end; + end + end +end %Add noise SET(NO).IM = SET(NO).IM+noisef*randn(size(SET(NO).IM)); @@ -1227,6 +1293,11 @@ function t2starphantom(noisef) segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %---------------------- function taggingphantom %---------------------- @@ -1295,6 +1366,11 @@ function t2starphantom(noisef) SET(NO).ImageViewPlane = 'Short-axis'; segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------------------------- function [res] = vel2segment(vel,venc) %------------------------------------- @@ -1350,8 +1426,8 @@ function t2starphantom(noisef) function petphantom %------------------ % PET phantom -% John Heerfordt Sjöqvist & Mattias Albinsson -global SET NO +% John Heerfordt Sj?qvist & Mattias Albinsson +global DATA SET NO %Set image size nx = 64; @@ -1469,6 +1545,11 @@ function t2starphantom(noisef) SET(no).TimeVector = t_frames; SET(no).TIncr = []; +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------------------- function C_a = input_function(t) %------------------------------- diff --git a/source/plotboxpos.m b/source/plotboxpos.m index 0cdbb8f..b19470f 100644 --- a/source/plotboxpos.m +++ b/source/plotboxpos.m @@ -8,7 +8,7 @@ % which may differ from the actual axis position, depending on the axis % limits, data aspect ratio, and plot box aspect ratio. The position is % returned in the same units as the those used to define the axis itself. -% This function can only be used for a 2D plot. +% This function can only be used for a 2D plot. % % Input variables: % @@ -21,11 +21,11 @@ % Check input if nargin < 1 - h = gca; + h = gca; end if ~ishandle(h) || ~strcmp(get(h,'type'), 'axes') - error('Input must be an axis handle'); + error('Input must be an axis handle'); end % Get position of axis in pixels @@ -41,45 +41,43 @@ if ~darismanual && ~pbarismanual - pos = axisPos; + pos = axisPos; else - dx = diff(get(h, 'XLim')); - dy = diff(get(h, 'YLim')); - dar = get(h, 'DataAspectRatio'); - pbar = get(h, 'PlotBoxAspectRatio'); - limDarRatio = (dx/dar(1))/(dy/dar(2)); - pbarRatio = pbar(1)/pbar(2); - axisRatio = axisPos(3)/axisPos(4); - - if darismanual - if limDarRatio > axisRatio - pos(1) = axisPos(1); - pos(3) = axisPos(3); - pos(4) = axisPos(3)/limDarRatio; - pos(2) = (axisPos(4) - pos(4))/2 + axisPos(2); - else - pos(2) = axisPos(2); - pos(4) = axisPos(4); - pos(3) = axisPos(4) * limDarRatio; - pos(1) = (axisPos(3) - pos(3))/2 + axisPos(1); - end - elseif pbarismanual - if pbarRatio > axisRatio - pos(1) = axisPos(1); - pos(3) = axisPos(3); - pos(4) = axisPos(3)/pbarRatio; - pos(2) = (axisPos(4) - pos(4))/2 + axisPos(2); - else - pos(2) = axisPos(2); - pos(4) = axisPos(4); - pos(3) = axisPos(4) * pbarRatio; - pos(1) = (axisPos(3) - pos(3))/2 + axisPos(1); - end + dx = diff(get(h, 'XLim')); + dy = diff(get(h, 'YLim')); + dar = get(h, 'DataAspectRatio'); + pbar = get(h, 'PlotBoxAspectRatio'); + limDarRatio = (dx/dar(1))/(dy/dar(2)); + pbarRatio = pbar(1)/pbar(2); + axisRatio = axisPos(3)/axisPos(4); + + if darismanual + if limDarRatio > axisRatio + pos(1) = axisPos(1); + pos(3) = axisPos(3); + pos(4) = axisPos(3)/limDarRatio; + pos(2) = (axisPos(4) - pos(4))/2 + axisPos(2); + else + pos(2) = axisPos(2); + pos(4) = axisPos(4); + pos(3) = axisPos(4) * limDarRatio; + pos(1) = (axisPos(3) - pos(3))/2 + axisPos(1); end + elseif pbarismanual + if pbarRatio > axisRatio + pos(1) = axisPos(1); + pos(3) = axisPos(3); + pos(4) = axisPos(3)/pbarRatio; + pos(2) = (axisPos(4) - pos(4))/2 + axisPos(2); + else + pos(2) = axisPos(2); + pos(4) = axisPos(4); + pos(3) = axisPos(4) * pbarRatio; + pos(1) = (axisPos(3) - pos(3))/2 + axisPos(1); + end + end end - - % Convert plot box position to the units used by the axis temp = axes('Units', 'Pixels', 'Position', pos, 'Visible', 'off', 'parent', get(h, 'parent')); set(temp, 'Units', currunit); diff --git a/source/plugin_CSPAMM.m b/source/plugin_CSPAMM.m index 43c09a8..bf84cf4 100644 --- a/source/plugin_CSPAMM.m +++ b/source/plugin_CSPAMM.m @@ -91,5 +91,5 @@ SET(nonew).IntensityOffset = 0; %close the gui -close(DATA.GUI.cspammreconstruct.fig) -segment('viewrefreshall_Callback')%mymsgbox('Click refresh!'); \ No newline at end of file +close(DATA.GUI.cspammreconstruct.fig) +viewfunctions('setview'); diff --git a/source/plugin_calibrate.m b/source/plugin_calibrate.m index 45358b8..c7a62b7 100644 --- a/source/plugin_calibrate.m +++ b/source/plugin_calibrate.m @@ -126,7 +126,7 @@ close(DATA.GUI.PluginCalibrate); %Update graphically in Segment to get grid around image panels correct. -drawfunctions('drawimageno'); +viewfunctions('setview'); %drawfunctions('drawimageno'); %------------ function draw diff --git a/source/plugin_exporttofourflow.m b/source/plugin_exporttofourflow.m index 3d1a7d6..df2e416 100644 --- a/source/plugin_exporttofourflow.m +++ b/source/plugin_exporttofourflow.m @@ -4,7 +4,7 @@ %Plugin for export flow to fourflow if nargin==0 myfailed('Need at least one input argument.'); -end; +end switch fcn case 'getname' @@ -14,9 +14,6 @@ %Set the main "summarize" menu to not perform a callback. set(varargin{1},'Callback',''); - %Check if valid license, then display options - %if isequal(3,getmodule(2,'3',[],true)) %'' => make license check silent. - %Register submenus uimenu(varargin{1},'Label','Background correction...','Callback','plugin_exporttofourflow(''background'')'); uimenu(varargin{1},'Label','Remove outer "zero-border" (if needed)','Callback', 'plugin_exporttofourflow(''fixisoborders'')'); @@ -47,7 +44,7 @@ otherwise macro_helper(fcn,varargin{:}); [varargout{1:nargout}] = feval(fcn,varargin{:}); % FEVAL switchyard -end; +end %-------------------------------- function fixisoborders %#ok @@ -108,7 +105,7 @@ question = {'Select Nbr of heart cycles: '}; dlgtitle = 'Please select desired number of heartbeats: '; default = {'2'}; -userinput = inputdlg(question, dlgtitle, 1, default); +userinput = myinputdlg(question, dlgtitle, 1, default); reps = round(str2double(userinput{1})); if reps>1 @@ -152,7 +149,7 @@ function background(varargin) %#ok if no < 1 || no > length(SET) || isempty(SET(no).Flow) myfailed('Error need to be flow data to do automatic background correction.'); return; -end; +end %Ensure that no is magnitude image no = SET(no).Flow.MagnitudeNo; @@ -165,7 +162,7 @@ function background(varargin) %#ok if isempty([nx ny nz]) myfailed('Error need to be flow data to do automatic background correction.'); return; -end; +end %--- User input dostore = yesno('Do you want to store background correction?', [], DATA.GUI.Segment); @@ -183,9 +180,9 @@ function background(varargin) %#ok '4th order'); if isequal(dim,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end dim = dim-1; %since first choice should return 0 @@ -197,9 +194,9 @@ function background(varargin) %#ok [instruct,ok] = inputstruct(instruct,'Enter settings'); if ~ok - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end if SET(no).ZSize == 1 if instruct.VoxelEdgeCut > 0.15*min([SET(no).XSize SET(no).YSize]) @@ -211,11 +208,11 @@ function background(varargin) %#ok myfailed('Too large edge cut. Aborted.'); return; end -end; +end if instruct.MagnitudeThresholdPercentage>70 myfailed('Too large magnitude threshold (max 70). Aborted.'); return; -end; +end %If dostore then 4 new image stacks are formed with mag,and phasecorrection. %If dostaticphantom is used to do background correction for flow phantoms @@ -263,7 +260,7 @@ function background(varargin) %#ok x.^3 y.^3 z.^3 x.^2.*y x.^2.*z y.^2.*x y.^2.*z z.^2.*x z.^2.*y x.*y.*z ... x.^4 y.^4 z.^4 x.^3.*y x.^3.*z y.^3.*x y.^3.*z z.^3.*x z.^3.*y x.^2.*y.^2 x.^2.*z.^2 x.^2.*y.*z y.^2.*z.^2 y.^2.*x.*z z.^2.*x.*y ... ]; -end; +end switch datatype case {'in vivo', 'static phantom'} @@ -344,11 +341,11 @@ function background(varargin) %#ok velmag = repmat(single(0),[SET(no).XSize,SET(no).YSize 1 SET(no).ZSize]); for nloop=1:length(nop) velmag = velmag+max(abs(SET(nop(nloop)).IM-single(0.5)),[],3).^2; - end; + end velmag = sqrt(velmag); sdw(velmag>0.04) = 0; %0.05 = 10% of VENC clear velmag; -end; +end %Extract which ones to take logind = (sdw~=0); @@ -372,10 +369,10 @@ function background(varargin) %#ok axis tight colorbar; -if ~yesno('Do you want to proceed?', [], DATA.GUI.Segment); +if ~yesno('Do you want to proceed?', [], DATA.GUI.Segment) myworkoff; return; -end; +end if dostore %If dostore create new image stacks @@ -395,12 +392,12 @@ function background(varargin) %#ok nextno = nextno+1; end -end; +end %Loop over the three velocity components. h = waitbar(0,'Please wait background correction.'); savewarn = warning; -warning off; %#ok +warning off; XVcut = XV(logind,:); @@ -421,7 +418,7 @@ function background(varargin) %#ok if dostore SET(nw).IM(:,:,tloop,:) = w; - end; + end % Loop over directions for nloop=1:3 @@ -448,7 +445,7 @@ function background(varargin) %#ok end waitbar(stepsdone/steps,h); -end; +end close(h); warning(savewarn); @@ -545,21 +542,21 @@ function background(varargin) %#ok if isempty(flowno) myfailed('No 3D flow image stacks found',DATA.GUI.Segment); return; -end; +end %Ask in a menu if more than one 4D flow if length(flowno)>1 names = cell(1,length(flowno)); for loop=1:length(flowno) names{loop} = sprintf('Stack %d: %s',flowno(loop),SET(flowno(loop)).ImageType); - end; + end m = mymenu('Choose 3D image stack to take from',names{:}); if isequal(m,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; - end; + end flowno = flowno(m); -end; +end %-------------------------------- @@ -578,7 +575,7 @@ function background(varargin) %#ok not(isempty(SET(nloop).Flow.PhaseY)) && ... isequal(SET(nloop).Flow.MagnitudeNo,nloop) flownos = [flownos nloop]; %#ok - end; + end end @@ -604,25 +601,25 @@ function background(varargin) %#ok outim = zeros([size(z,1) size(z,2) frames size(z,4)]); else outim = repmat(single(0),[size(z,1) size(z,2) frames size(z,4)]); - end; + end switch ndims(z) case 3 for tloop=1:length(intpos) outim(:,:,tloop) = ... (1-intpos(tloop)+intleft(tloop))*z(:,:,intleft(tloop))+... (1-intright(tloop)+intpos(tloop))*z(:,:,intright(tloop)); - end; + end case 4 for tloop=1:length(intpos) outim(:,:,tloop,:) = ... (1-intpos(tloop)+intleft(tloop))*z(:,:,intleft(tloop),:)+... (1-intright(tloop)+intpos(tloop))*z(:,:,intright(tloop),:); - end; + end otherwise myfailed('Upsampling in time not defined for this dimensionality.'); - end; - end; %Timeresolved clause + end + end %Timeresolved clause else %Copy outim = z; -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/plugin_imageloader.m b/source/plugin_imageloader.m index 8b9f46b..847cb82 100644 --- a/source/plugin_imageloader.m +++ b/source/plugin_imageloader.m @@ -11,7 +11,7 @@ if nargin==0 myfailed('Expects at least one input argument.'); return; -end; +end switch fcn case 'getname' @@ -45,7 +45,7 @@ otherwise macro_helper(fcn,varargin{:}); [varargout{1:nargout}] = feval(fcn,varargin{:}); % FEVAL switchyard -end; +end %--------------------- function resetpreview @@ -106,6 +106,11 @@ openfile('setupstacksfromdicom',NO); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------------- function loadmany_Callback %#ok %------------------------- @@ -121,17 +126,17 @@ files = dir([pathname filesep '*.jpg']); if isempty(files) files = dir([pathname filesep '*.JPG']); -end; +end if isempty(files) myfailed('Could not find any files.'); -end; +end %Get factor [f,ok] = mygetnumber('Enter upsampling/downsampling factor (<1 => downsample)','Resampling Factor',0.1,0,10); if ~ok myfailed('Invalid upsampling/downsampling factor or aborted.'); return; -end; +end h = waitbar(0,'Please wait.'); for fileloop = 1:length(files) @@ -155,9 +160,14 @@ segment('renderstacksfromdicom',NO); waitbar(fileloop/length(files),h); -end; +end close(h); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %------------------------ function loaddir_Callback %#ok %------------------------ @@ -206,6 +216,11 @@ openfile('setupstacksfromdicom',NO); segment('renderstacksfromdicom',NO); +%Does all graphical updates +if not(isempty(DATA.ViewMatrix)) + DATA.init_graphics; +end + %----------------------- function r = isimage(f) %----------------------- diff --git a/source/plugin_summarize.m b/source/plugin_summarize.m index b231dfd..34522be 100644 --- a/source/plugin_summarize.m +++ b/source/plugin_summarize.m @@ -9,7 +9,7 @@ if nargin==0 myfailed('Requires more than one input argument.'); return; -end; +end switch fcn case 'getname' @@ -49,7 +49,7 @@ otherwise macro_helper(fcn,varargin{:}); [varargout{1:nargout}] = feval(fcn,varargin{:}); % FEVAL switchyard -end; +end %------------------------------ function [outdata,ind] = header @@ -115,9 +115,9 @@ pathname = DATA.Pref.datapath; pathname = myuigetdir(pathname,'Select a folder with .mat files'); if isequal(pathname,0) - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end %Find files to process files2load = dir([pathname filesep '*.mat']); @@ -126,7 +126,7 @@ if numfiles==0 myfailed('Found no files to summarize.'); return; -end; +end includenormalized = yesno('Do you want to include BSA normalized values?'); @@ -137,7 +137,7 @@ %--- Write header for loop=1:length(temp) outdata{1,loop} = temp{loop}; -end; +end %Loop over all files h = mywaitbarstart(numfiles,'Please wait, loading and summarizing files.',1); @@ -169,9 +169,9 @@ %Call one to get info in one line. temp = one(false); %no header; - for loop=2:size(temp,2); + for loop=2:size(temp,2) outdata{fileloop+1,loop} = temp{1,loop}; - end; + end %Do special with flow and multiple @@ -195,10 +195,10 @@ outdata{fileloop+1,roipos} = SET(NO).Roi(rloop).Name; outdata{fileloop+1,roipos+1} = tots(rloop); roipos = roipos+2; - end; - end; - end; - end; + end + end + end + end measurementpos = roipos; for sloop=1:length(SET) @@ -208,22 +208,22 @@ outdata{fileloop+1,measurementpos} = SET(sloop).Measure(mloop).Name; outdata{fileloop+1,measurementpos+1} = SET(sloop).Measure(mloop).Length; measurementpos = measurementpos+2; - end; - end; + end + end catch %#ok %--- Some thing went wrong outdata{fileloop+1,2} = 'FAILED.'; end h = mywaitbarupdate(h); -end; %loop over files +end %loop over files mywaitbarclose(h); %If not wanted remove non normalized values. ind = true(1,size(outdata,2)); if ~includenormalized ind(indforbsa) = false; -end; +end outdata = outdata(:,ind); %--- Output to a string @@ -247,13 +247,13 @@ if isnan(no) no = NO; -end; +end outdata = cell(1,20); if nargin==0 doheader = true; -end; +end if doheader %Write Header @@ -261,11 +261,11 @@ row = 2; else row = 1; -end; +end if nargout>0 varargout = cell(1,nargout); -end; +end %Write data outdata{row, 1} = SET(no).FileName; @@ -285,13 +285,13 @@ rvm = 0.5*(SET(no).RVM(SET(no).EDT)+SET(no).RVM(SET(no).EST)); catch %#ok rvm = NaN; -end; +end if SET(no).PatientInfo.BSA==0 bsa_1 = NaN; else bsa_1 = 1/SET(no).BSA; -end; +end outdata{row,12} = lvm; outdata{row,13} = lvm*1.05; @@ -328,13 +328,13 @@ scar2use = false(size(scarno)); for sloop=1:length(scarno) scar2use(sloop) = existfunctions('existendo',scarno(sloop)) && not(isempty(SET(scarno(sloop)).Scar)); - end; + end scarno = scarno(scar2use); if length(scarno)>1 mywarning('Detected multiple scar data. Taking first (arbitrary decision)'); scarno = scarno(1); %Take first just arbitrary. - end; -end; + end +end if ~isempty(scarno) lvmde = SET(scarno).LVM(SET(scarno).EDT); @@ -382,10 +382,10 @@ %For backwards compability. if isnan(SET(scarno).Scar.MOPercentage) viability('viabilitycalcvolume',scarno); - end; + end outdata{row,46} = SET(scarno).Scar.MOPercentage; - end; + end else outdata{row,36} = NaN; outdata{row,37} = NaN; @@ -398,7 +398,7 @@ outdata{row,44} = NaN; outdata{row,45} = NaN; outdata{row,46} = NaN; -end; +end %Flow @@ -416,14 +416,14 @@ for rloop=1:length(tots) if doheader outdata{1,roipos} = sprintf('%s[tot ml]',SET(NO).Roi(rloop).Name); - end; + end outdata{row,roipos} = tots(rloop); roipos = roipos+1; - end; - end; + end + end - end; -end; + end +end %Measurements measurementpos = roipos; @@ -431,15 +431,15 @@ for mloop=1:length(SET(sloop).Measure) if doheader outdata{1,measurementpos} = [SET(sloop).Measure(mloop).Name '[mm]']; - end; + end outdata{row,measurementpos} = SET(sloop).Measure(mloop).Length; measurementpos = measurementpos+1; - end; -end; + end +end %If called with no output arguments then copy to clipboard. if nargout==0 segment('cell2clipboard',outdata); else varargout{1} = outdata; -end; \ No newline at end of file +end \ No newline at end of file diff --git a/source/plugins.mat b/source/plugins.mat index 9266ccd..62a7394 100644 Binary files a/source/plugins.mat and b/source/plugins.mat differ diff --git a/source/pushtobuffer.m b/source/pushtobuffer.m index 677b468..4fcb9ae 100644 --- a/source/pushtobuffer.m +++ b/source/pushtobuffer.m @@ -9,7 +9,7 @@ function pushtobuffer(f,o) if nargin<2 error('Expected two input arguments.'); -end; +end buffer = DATA.Buffer.(f); isacell = iscell(buffer); @@ -17,7 +17,7 @@ function pushtobuffer(f,o) buffer = [{o} buffer]; else buffer = [o buffer]; -end; +end %Store it. DATA.Buffer.(f) = buffer; diff --git a/source/readmedvisoinfo.mexw32 b/source/readmedvisoinfo.mexw32 deleted file mode 100644 index 10f36b9..0000000 Binary files a/source/readmedvisoinfo.mexw32 and /dev/null differ diff --git a/source/reformater.fig b/source/reformater.fig index 582d292..9a3ecec 100644 Binary files a/source/reformater.fig and b/source/reformater.fig differ diff --git a/source/reformater.p b/source/reformater.p index 9dee7f3..d4da766 100644 Binary files a/source/reformater.p and b/source/reformater.p differ diff --git a/source/removeinvalidchars.m b/source/removeinvalidchars.m index 0d80461..5afd73a 100644 --- a/source/removeinvalidchars.m +++ b/source/removeinvalidchars.m @@ -6,12 +6,12 @@ %This code can be written more elegant, but who cares, it works and is fast %enough. -valid = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$@£{}[]()+-:,;<>|'; +valid = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$@?{}[]()+-:,;<>|'; logvec = false(size(stri)); for loop = 1:length(stri) if sum(stri(loop)==valid)>0 logvec(loop) = true; - end; -end; + end +end outstri = stri(logvec); diff --git a/source/report3dmodel.m b/source/report3dmodel.m index b0dee78..fb9dd20 100644 --- a/source/report3dmodel.m +++ b/source/report3dmodel.m @@ -34,14 +34,14 @@ function report3dmodel(varargin) gui.t = segment('getframenumber'); pause(0.5*SET(gui.no).BeatTime/SET(gui.no).TSize); report3dmodel('update'); - end; + end case 'radialvel' if get(gui.handles.radialvelradiobutton,'value') gui.handles.radvel = calcfunctions('calcradialvelocity',gui.no); else set(DATA.Handles.endosurf,... 'Cdata',repmat(97,size(EndoX,1),size(EndoX,3))); - end; + end report3dmodel('update'); case 'prev' i=find(gui.t==gui.indTn); @@ -74,12 +74,12 @@ function report3dmodel(varargin) delete(4); catch %#ok %Do nothing if failed - end; + end try delete(gui.fig); catch %#ok %Do nothing if failed - end; + end DATA.GUI.Report3DModel = []; case 'update' %--- Refresh the display @@ -103,14 +103,14 @@ function report3dmodel(varargin) %97 = 64+1+32 set(DATA.Handles.endosurf,... 'Cdata',97+(32/DATA.MaxRadialVel)*squeeze(gui.handles.radvel(:,t,ind))); - end; + end else try set(DATA.Handles.endosurf,'visible','off'); catch %#ok - end; + end - end; + end %Update episurf if get(gui.handles.epicheckbox,'value') @@ -124,8 +124,8 @@ function report3dmodel(varargin) try set(DATA.Handles.episurf,'visible','off'); catch %#ok - end; - end; + end + end %Update RVendo surf if get(gui.handles.rvendocheckbox,'value') @@ -139,8 +139,8 @@ function report3dmodel(varargin) try set(DATA.Handles.rvendosurf,'visible','off'); catch %#ok - end; - end; + end + end %Update RVepi surf if get(gui.handles.rvepicheckbox,'value') @@ -154,8 +154,8 @@ function report3dmodel(varargin) try set(DATA.Handles.rvepisurf,'visible','off'); catch %#ok - end; - end; + end + end %Update annotation points if mygetvalue(gui.handles.annotationpointscheckbox) @@ -168,7 +168,7 @@ function report3dmodel(varargin) try set(DATA.Handles.annotationpoints3d,'visible','off'); catch %#ok - end; + end end @@ -185,7 +185,7 @@ function report3dmodel(varargin) try set(DATA.Handles.measurements3d,'visible','off'); catch %#ok - end; + end end %Update scar @@ -199,7 +199,7 @@ function report3dmodel(varargin) try set(DATA.Handles.scar3d,'visible','off'); catch %#ok - end; + end end %Update short axis slice @@ -214,7 +214,7 @@ function report3dmodel(varargin) 'CDATA',1+(63*double(squeeze(SET(gui.no).IM(:,:,gui.t,slice))))); else set(DATA.Handles.lvcutshort,'visible','off'); - end; + end %Update long-axis slice if get(gui.handles.longslicescheckbox,'value') @@ -225,63 +225,64 @@ function report3dmodel(varargin) 'Cdata',1+(63*double(squeeze(SET(gui.no).IM(:,round(z),gui.t,:))))); else set(DATA.Handles.lvcutlong,'visible','off'); - end; + end if DATA.Record drawnow; DATA.MovieFrame = mygetframe(4); export('exportmovierecorder_Callback','newframe'); - end; + end %catch %Did not manage to update correctly, give it up! % report3dmodel('close'); - %end; - end; -end; + %end + end +end %---------------------------- function report3dmodelrotated %---------------------------- %Display 3D model of rotated image stacks. -global DATA SET NO +global SET NO -figure(88); +fig = figure(88); clf; hold on; - -if isequal(get(DATA.Handles.hidelvicon,'state'),'off') - if ~isempty(SET(NO).EndoX); +stateandicon = viewfunctions('iconson',{'hidelv','hiderv'}); +state = [stateandicon{:,1}]; +if state(1) + if ~isempty(SET(NO).EndoX) rotatedplothelper(... SET(NO).EndoX,... SET(NO).EndoY,... 'r-'); - end; + end - if ~isempty(SET(NO).EpiX); + if ~isempty(SET(NO).EpiX) rotatedplothelper(... SET(NO).EpiX,... SET(NO).EpiY,... 'g-'); - end; -end; + end +end -if isequal(get(DATA.Handles.hidervicon,'state'),'off') - if ~isempty(SET(NO).RVEndoX); +if state(2) + if ~isempty(SET(NO).RVEndoX) rotatedplothelper(... SET(NO).RVEndoX,... SET(NO).RVEndoY,... 'm-'); - end; + end - if ~isempty(SET(NO).RVEpiX); + if ~isempty(SET(NO).RVEpiX) rotatedplothelper(... SET(NO).RVEpiX,... SET(NO).RVEpiY,... 'c-'); - end; -end; + end +end ind = find(SET(NO).Point.T==SET(NO).CurrentTimeFrame); for loop=1:length(ind) @@ -292,13 +293,13 @@ function report3dmodel(varargin) SET(NO).ZSize,... SET(NO).RotationCenter); plot3(x,y,z,'r*'); -end; +end axis image off; hold off; -set(88,'Numbertitle','off','Name','3D visualization of rotated stacks.'); -cameratoolbar(88,'show'); +set(fig,'Numbertitle','off','Name','3D visualization of rotated stacks.'); +cameratoolbar(fig,'show'); %------------------------------------------ function rotatedplothelper(xc,yc,linecolor) @@ -313,7 +314,7 @@ function rotatedplothelper(xc,yc,linecolor) for zloop=1:SET(NO).ZSize xmin = min(min(xc(:,tf,zloop)),xmin); xmax = max(max(xc(:,tf,zloop)),xmax); -end; +end xrange = linspace(xmin,xmax,20); @@ -326,7 +327,7 @@ function rotatedplothelper(xc,yc,linecolor) SET(NO).ZSize,... %Number of slices SET(NO).RotationCenter); %Rotation center plot3(x,y,z,linecolor); -end; +end %---Draw_lines @@ -352,8 +353,8 @@ function rotatedplothelper(xc,yc,linecolor) r = [r SET(NO).RotationCenter-yt(ind(iloop))]; %#ok slice = [slice zloop+SET(NO).ZSize]; %#ok end - end; - end; + end + end %--- "Sort it" while ~isempty(slice) @@ -377,7 +378,7 @@ function rotatedplothelper(xc,yc,linecolor) %Continue along the slices nextslice = nextslice+1; - end; + end %--- Plot the line section if length(drawr)>1 @@ -392,8 +393,8 @@ function rotatedplothelper(xc,yc,linecolor) isequal(drawslice(end),SET(NO).ZSize*2) drawslice = [drawslice linspace(0,1,10)]; %#ok drawr = [drawr interp1([drawr(end) drawr(1)],linspace(1,2,10))]; %#ok - end; - end; + end + end angle = (drawslice-1)*pi/SET(NO).ZSize; x = drawr.*sin(angle)+SET(NO).RotationCenter; @@ -401,9 +402,9 @@ function rotatedplothelper(xc,yc,linecolor) z = repmat(xrange(loop),size(x)); plot3(x,y,z,linecolor); - end; - end; -end; %Loop over rows + end + end +end %Loop over rows %------------ function init @@ -411,27 +412,20 @@ function rotatedplothelper(xc,yc,linecolor) %initiating the 3D model interface global DATA SET NO -try - set(DATA.Handles.model3icon,'state','off'); -catch %#ok - close(gcf); - return; %Segment have most likely been closed. -end; - if SET(NO).Rotated report3dmodelrotated; return; -end; +end if SET(NO).ZSize<2 myfailed('Need to have more than one slice for viewing 3D-model.',DATA.GUI.Segment); return; -end; +end if isempty(SET(NO).EndoX) || all(isnan(SET(NO).EndoX(:))) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end tempnos=NO; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -443,10 +437,10 @@ function rotatedplothelper(xc,yc,linecolor) if SET(NO).TSize>1 if isequal(SET(NO).EDT,SET(NO).EST) mywarning('Warning, end-diastole occurs at the same time as end-systole. Use autodetect under edit menu.',DATA.GUI.Segment); - end; - end; + end + end - segment('checkconsistency',1:SET(NO).TSize,1:SET(NO).ZSize); +% segment('checkconsistency',1:SET(NO).TSize,1:SET(NO).ZSize); doepi = ~isempty(SET(NO).EpiX) && ~all(isnan(SET(NO).EpiX(:))); dorvendo = ~isempty(SET(NO).RVEndoX) && ~all(isnan(SET(NO).RVEndoX(:))); @@ -499,6 +493,7 @@ function rotatedplothelper(xc,yc,linecolor) %Create plot figure plotfig = figure(4); + setupicon(plotfig); set(plotfig,'units','pixels','position',[193 200 500 500]); set(plotfig,'renderer','opengl',... 'Name','3D model',... @@ -512,7 +507,7 @@ function rotatedplothelper(xc,yc,linecolor) DATA.GUI.Report3DModel = gui; % Use system color scheme for figure: - set(gui.fig,'Color',get(0,'defaultUicontrolBackgroundColor')); + set(gui.fig,'Color',DATA.GUISettings.BackgroundColor); %get(0,'defaultUicontrolBackgroundColor')); gui.closing=false; @@ -524,7 +519,7 @@ function rotatedplothelper(xc,yc,linecolor) % else % gui.basalslice = 1; % gui.numslice = 0; -% end; +% end gui.numslices=nslices; gui.basalslice=1; gui.t = t; @@ -580,17 +575,17 @@ function rotatedplothelper(xc,yc,linecolor) set(gui.handles.epicheckbox,'enable','off'); else set(gui.handles.epicheckbox,'value',1); - end; + end if ~dorvendo set(gui.handles.rvendocheckbox,'enable','off'); else set(gui.handles.rvendocheckbox,'value',1); - end; + end if ~dorvepi set(gui.handles.rvepicheckbox,'enable','off'); else set(gui.handles.rvepicheckbox,'value',1); - end; + end if ~dopoints set(gui.handles.annotationpointscheckbox,'enable','off'); else @@ -618,14 +613,14 @@ function rotatedplothelper(xc,yc,linecolor) gui.handles.epicheckbox... gui.handles.rvendocheckbox... gui.handles.rvepicheckbox],'enable','off'); - end; + end if nslices>2 gui.EndoX = SET(NO).ResolutionX*SET(NO).EndoX; gui.EndoY = SET(NO).ResolutionY*SET(NO).EndoY; gui.EndoZ = repmat((1-(1:SET(NO).ZSize))*(SET(NO).SliceThickness+SET(NO).SliceGap),... [DATA.NumPoints 1]); - + if doepi gui.EpiX = SET(NO).ResolutionX*SET(NO).EpiX; gui.EpiY = SET(NO).ResolutionY*SET(NO).EpiY; @@ -646,11 +641,11 @@ function rotatedplothelper(xc,yc,linecolor) % if doepi % tempxepi = SET(NO).ResolutionX*SET(NO).EpiX(:,:,ind); % tempyepi = SET(NO).ResolutionY*SET(NO).EpiY(:,:,ind); -% end; +% end % if dorv % tempxrvendo = SET(NO).ResolutionX*SET(NO).RVEndoX(:,:,ind); % tempyrvendo = SET(NO).ResolutionY*SET(NO).RVEndoY(:,:,ind); -% end; +% end % % newzsize = max(16,nslices); %Number of planes to resample it to. % EndoX = zeros(... @@ -666,7 +661,7 @@ function rotatedplothelper(xc,yc,linecolor) % newzsize); % EpiY = EpiX; % EpiZ = EndoZ; -% end; +% end % if dorv % RVEndoX = zeros(... % size(SET(NO).RVEndoX,1),... @@ -691,7 +686,7 @@ function rotatedplothelper(xc,yc,linecolor) % %temp2=>0 at EDT, temp2=>1 at EST % temp = temp*temp2; % newind = linspace(temp,1,newzsize); -% end; +% end % %Resample endocardium % EndoX(:,tloop,:) = interp1(... % linspace(0,1,nslices)',... @@ -711,7 +706,7 @@ function rotatedplothelper(xc,yc,linecolor) % linspace(0,1,nslices)',... % squeeze(tempyepi(:,tloop,:))',... % newind')'; -% end; +% end % if dorv % %Resample RV endocardium % RVEndoX(:,tloop,:) = interp1(... @@ -729,7 +724,7 @@ function rotatedplothelper(xc,yc,linecolor) % sum(ind)*(SET(NO).SliceThickness+SET(NO).SliceGap); % RVEndoZ(tloop,:) = newind*... % sum(ind)*(SET(NO).SliceThickness+SET(NO).SliceGap); -% end; +% end % clear tempxendo tempyendo tempxepi tempyepi; %-------------- @@ -739,7 +734,10 @@ function rotatedplothelper(xc,yc,linecolor) %RVEndoX RVEndoY RVEndoZ %--- Create RV EndoZ, EpiZ - gui.RVEndoZ = repmat(-(1:SET(NO).ZSize)*(SET(NO).SliceThickness+SET(NO).SliceGap),... + %gui.RVEndoZ = repmat(-(1:SET(NO).ZSize)*(SET(NO).SliceThickness+SET(NO).SliceGap),... + % [DATA.NumPoints 1]); %Changed 2020-07-26 after bug-report + + gui.RVEndoZ = repmat((1-(1:SET(NO).ZSize))*(SET(NO).SliceThickness+SET(NO).SliceGap),... [DATA.NumPoints 1]); %--- Create RV EndoX, EndoY, EpiX, EpiY @@ -782,18 +780,21 @@ function rotatedplothelper(xc,yc,linecolor) gui.RVEndoY(1:(DATA.NumPoints-inda+1),tloop,zloop) = yr(inda:end); gui.RVEndoX((DATA.NumPoints+1-inda):end,tloop,zloop) = xr(1:inda); gui.RVEndoY((DATA.NumPoints+1-inda):end,tloop,zloop) = yr(1:inda); - end; - end; - end; + end + end + end end if dorvepi %RVEndoX RVEndoY RVEndoZ %--- Create RVEndoZ - gui.RVEpiZ = repmat(-(1:SET(NO).ZSize)*(SET(NO).SliceThickness+SET(NO).SliceGap),... + %gui.RVEpiZ = repmat(-(1:SET(NO).ZSize)*(SET(NO).SliceThickness+SET(NO).SliceGap),... + % [DATA.NumPoints 1]); %Fixed 2020-07-26 after bug report. + gui.RVEpiZ = repmat((1-(1:SET(NO).ZSize))*(SET(NO).SliceThickness+SET(NO).SliceGap),... [DATA.NumPoints 1]); + %--- Create EndoX, EndoY gui.RVEpiX = SET(NO).ResolutionX*SET(NO).RVEpiX; gui.RVEpiY = SET(NO).ResolutionY*SET(NO).RVEpiY; @@ -834,9 +835,9 @@ function rotatedplothelper(xc,yc,linecolor) gui.RVEpiY(1:(DATA.NumPoints-inda+1),tloop,zloop) = yr(inda:end); gui.RVEpiX((DATA.NumPoints+1-inda):end,tloop,zloop) = xr(1:inda); gui.RVEpiY((DATA.NumPoints+1-inda):end,tloop,zloop) = yr(1:inda); - end; - end; - end; + end + end + end end %Prepare annotation points @@ -887,19 +888,19 @@ function rotatedplothelper(xc,yc,linecolor) gui.EpiX(:,:,end+1) = mean(mean(gui.EpiX(:,:,1))); gui.EpiY(:,:,end+1) = mean(mean(gui.EpiY(:,:,1))); gui.EpiZ(:,end+1) = gui.EpiZ(:,end)+(SET(NO).SliceThickness+SET(NO).SliceGap); - end; + end if dorvendo gui.RVEndoX(:,:,end+1) = mean(mean(gui.RVEndoX(:,:,1))); gui.RVEndoY(:,:,end+1) = mean(mean(gui.RVEndoY(:,:,1))); gui.RVEndoZ(:,end+1) = gui.RVEndoZ(:,end)+(SET(NO).SliceThickness+SET(NO).SliceGap); - end; + end if dorvepi gui.RVEpiX(:,:,end+1) = mean(mean(gui.RVEpiX(:,:,1))); gui.RVEpiY(:,:,end+1) = mean(mean(gui.RVEpiY(:,:,1))); gui.RVEpiZ(:,end+1) = gui.RVEpiZ(:,end)+(SET(NO).SliceThickness+SET(NO).SliceGap); - end; - end; - end; + end + end + end %------- Draw %Create endocardium @@ -925,7 +926,7 @@ function rotatedplothelper(xc,yc,linecolor) 'AlphaDataMapping','none',... 'AlphaData',repmat(0.5,[size(gui.EpiX,1) size(gui.EpiX,3)]),... 'FaceColor','green'); - end; + end if dorvendo DATA.Handles.rvendosurf = surf(... squeeze(gui.RVEndoX(:,t,:)),... %EH: diff --git a/source/reportbullseye.m b/source/reportbullseye.m index 01c2dcf..21bb14f 100644 --- a/source/reportbullseye.m +++ b/source/reportbullseye.m @@ -23,15 +23,13 @@ global DATA SET NO -set(DATA.Handles.reportbullseyeicon,'state','off'); - if isempty(SET(NO).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; elseif isempty(SET(NO).EpiX) myfailed('No LV epicardium available.',DATA.GUI.Segment); return; -end; +end tempnos = NO; imissingle = classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -69,7 +67,7 @@ myfailed('No slices selected.',DATA.GUI.Segment); % close_Callback; return; -end; +end %ensure current time frame have LV seg tf = SET(NO).CurrentTimeFrame; @@ -77,55 +75,61 @@ %change to first time frame with LV seg tffirst = find(~isnan(mynanmean(SET(NO).EndoX(1,:,:),3)),1,'first'); SET(NO).CurrentTimeFrame = tffirst; - segment('updatemodeldisplay'); - segment('makeviewim',DATA.CurrentPanel,NO); - drawfunctions('drawimageno',NO); + DATA.ViewIM{DATA.CurrentPanel} = []; + drawfunctions('drawno',NO); end +%KG, 2019-06-19 +%Took away resampling below because function for removing duplicate points already exists in +%calcfunctions('resamplecurve') +% %Resample model to ensure distributed points. -for tloop=1:SET(NO).TSize - for zloop=1:SET(NO).ZSize - - %Check endo - if not(isnan(SET(NO).EndoX(1,tloop,zloop))) - %Calculate distances between points - len = sqrt(... - conv2(SET(NO).EndoX(:,tloop,zloop),[1;-1],'valid').^2+... - conv2(SET(NO).EndoY(:,tloop,zloop),[1;-1],'valid').^2); - %Remove indices of duplicate points (len(i) == 0) - ind = [true; len > 0]; - len = len(ind(2:end)); - len = [0;len(:)]; %Add zero first - len = cumsum(len); - totallength = len(end); - - if totallength>0 - %Resample - SET(NO).EndoX(:,tloop,zloop) = interp1(len,SET(NO).EndoX(ind,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); - SET(NO).EndoY(:,tloop,zloop) = interp1(len,SET(NO).EndoY(ind,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); - end; - end; - - %Check epi - if ~isempty(SET(NO).EpiX) - if not(isnan(SET(NO).EpiX(1,tloop,zloop))) - len = sqrt(... - conv2(SET(NO).EpiX(:,tloop,zloop),[1;-1],'valid').^2+... - conv2(SET(NO).EpiY(:,tloop,zloop),[1;-1],'valid').^2); - len = [0;len(:)]; %Add zero first - len = cumsum(len); - totallength = len(end); - - if totallength>0 - %Resample - SET(NO).EpiX(:,tloop,zloop) = interp1(len,SET(NO).EpiX(:,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); - SET(NO).EpiY(:,tloop,zloop) = interp1(len,SET(NO).EpiY(:,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); - end; - end; - end; - - end; -end; +% for tloop=1:SET(NO).TSize +% for zloop=1:SET(NO).ZSize +% +% %Check endo +% if not(isnan(SET(NO).EndoX(1,tloop,zloop))) +% %Calculate distances between points +% len = sqrt(... +% conv2(SET(NO).EndoX(:,tloop,zloop),[1;-1],'valid').^2+... +% conv2(SET(NO).EndoY(:,tloop,zloop),[1;-1],'valid').^2); +% %Remove indices of duplicate points (len(i) == 0) +% ind = [true; len > 0]; +% len = len(ind(2:end)); +% len = [0;len(:)]; %Add zero first +% len = cumsum(len); +% totallength = len(end); +% +% if totallength>0 +% %Resample +% SET(NO).EndoX(:,tloop,zloop) = interp1(len,SET(NO).EndoX(ind,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); +% SET(NO).EndoY(:,tloop,zloop) = interp1(len,SET(NO).EndoY(ind,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); +% end +% end +% +% %Check epi +% if ~isempty(SET(NO).EpiX) +% if not(isnan(SET(NO).EpiX(1,tloop,zloop))) +% len = sqrt(... +% conv2(SET(NO).EpiX(:,tloop,zloop),[1;-1],'valid').^2+... +% conv2(SET(NO).EpiY(:,tloop,zloop),[1;-1],'valid').^2); +% %Remove indices of duplicate points (len(i) == 0) +% ind = [true; len > 0]; +% len = len(ind(2:end)); +% len = [0;len(:)]; %Add zero first +% len = cumsum(len); +% totallength = len(end); +% +% if totallength>0 +% %Resample +% SET(NO).EpiX(:,tloop,zloop) = interp1(len,SET(NO).EpiX(ind,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); +% SET(NO).EpiY(:,tloop,zloop) = interp1(len,SET(NO).EpiY(ind,tloop,zloop),linspace(0,totallength,DATA.NumPoints)); +% end +% end +% end +% +% end +% end gui = mygui('bullseye.fig'); DATA.GUI.Bullseye = gui; @@ -157,7 +161,7 @@ gui.numsectors = str2num(temp{mygetlistbox(gui.handles.sectorslistbox)}); %#ok end -set(gui.handles.slicetext,'String',sprintf('Slice %d',gui.slice)); +set(gui.handles.slicetext,'String',dprintf('Slice %d',gui.slice)); if SET(NO).ZSize > 1 set(gui.handles.sliceslider,'Min',1,'Max',... SET(NO).ZSize,'Value',SET(NO).ZSize-gui.slice+1,'SliderStep',... @@ -171,7 +175,7 @@ if isempty(gui.slice) gui.slice = 1; -end; +end if ~DATA.GUISettings.PointsEnabled set(gui.handles.rotationfromannotationcheckbox,'visible','off','value',0); @@ -249,7 +253,7 @@ else [x,y] = calcfunctions('calcplaneintersections',gui.no,gui.no,'hla','one',loop,hslice); end - if isempty(x) || isempty(y); + if isempty(x) || isempty(y) x = nan; y = nan; end @@ -295,7 +299,7 @@ function defineslices(sign,part) %#ok %check so gui.slice is inside selected slices gui.slice = min(max(gui.slice,SET(gui.no).StartSlice),SET(gui.no).EndSlice); set(gui.handles.sliceslider,'Value',SET(gui.no).ZSize-gui.slice+1); -set(gui.handles.slicetext,'String',sprintf('Slice %d',gui.slice)); +set(gui.handles.slicetext,'String',dprintf('Slice %d',gui.slice)); updatesliceimage; %update all views @@ -393,7 +397,7 @@ function defineslices(sign,part) %#ok case 17 stri = 'Apex'; pos = 17; -end; +end %-------------------------- function varargout = export %#ok @@ -412,8 +416,8 @@ function defineslices(sign,part) %#ok stri = [stri sprintf('\t')]; for sectorloop=size(gui.outdata,1):-1:1 stri = [stri sprintf('sector%d\t',sectorloop)]; %#ok - end; - stri = [stri sprintf('\n')]; + end + stri = [stri newline]; for sliceloop=1:size(gui.outdata,2) if sliceloop==1 stri = [stri sprintf('Slice%d (basal)\t',sliceloop)]; %#ok @@ -422,25 +426,25 @@ function defineslices(sign,part) %#ok stri = [stri sprintf('Slice%d (apical)\t',sliceloop)]; %#ok else stri = [stri sprintf('Slice%d\t',sliceloop)]; %#ok - end; - end; + end + end for sectorloop=1:size(gui.outdata,1) stri = [stri sprintf('%0.5g\t',gui.outdata(sectorloop,sliceloop))]; %#ok - end; - stri = [stri sprintf('\n')]; %#ok - end; + end + stri = [stri newline]; %#ok + end if nargout==0 clipboard('copy',stri); mymsgbox('Data copied to clipboard.','Done!',DATA.GUI.Segment); else varargout{1} = stri; - end; + end elseif mygetvalue(gui.handles.smoothradiobutton) %--- Smooth output to .bin file tempim = get(get(gui.handles.bullseyeaxes,'children'),'cdata'); if nargout==0 - filename = inputdlg({'Enter file name'},'File name',1,{sprintf('%s_%s',SET(gui.no).PatientInfo.ID,gui.parameter)}); + filename = myinputdlg({'Enter file name'},'File name',1,{sprintf('%s_%s',SET(gui.no).PatientInfo.ID,gui.parameter)}); fid = fopen([filename{1},'.bin'],'w'); fwrite(fid,tempim,'float32'); status = fclose(fid); @@ -452,15 +456,15 @@ function defineslices(sign,part) %#ok else stri = sprintf('%s\t%s\t%d\t%d\n',gui.parameter,gui.outunit,SET(gui.no).StartSlice,SET(gui.no).EndSlice); stri = [stri sprintf('\t')]; - stri = [stri sprintf('\n')]; + stri = [stri newline]; for rowloop = 1:size(tempim,1) for columnloop = 1:size(tempim,2) stri = [stri sprintf('%0.5g\t',tempim(rowloop,columnloop))]; %#ok end - stri = [stri sprintf('\n')]; %#ok + stri = [stri newline]; %#ok end varargout{1} = stri; - end; + end elseif mygetvalue(gui.handles.aharadiobutton) %--- AHA output outcell = cell(3,17); @@ -472,14 +476,14 @@ function defineslices(sign,part) %#ok stri,... gui.outunit); outcell{3,pos} = gui.ahaoutdata(loop); - end; + end outcell{1,1} = gui.parameter; if nargout==0 segment('cell2clipboard',outcell); else varargout{1} = segment('cell2clipboard',outcell); - end; -end; + end +end %--------------------------------------- function plotmethodpanel_SelectionChange %#ok @@ -506,7 +510,7 @@ function defineslices(sign,part) %#ok gui.numsectors = str2double(temp{mygetlistbox(gui.handles.sectorslistbox)}); set(gui.handles.volumeconsistentcheckbox,'enable','on'); gui.volumeconsistent = get(gui.handles.volumeconsistentcheckbox,'value'); -end; +end updateall; %--------------- @@ -552,13 +556,13 @@ function defineslices(sign,part) %#ok for loop = 1:length(SET(no).Point.Z) if isequal(SET(no).Point.Label{loop},'RV insertion') || isequal(SET(no).Point.Label{loop},'P1')|| isequal(SET(no).Point.Label{loop},'P2') slices(SET(no).Point.Z(loop)) = true; - end; -end; + end +end %Find slices pos = find(slices); if isempty(pos) - disp(dprintf('No RV points found. Current sector rotation is %0.5g',SET(no).SectorRotation)); + disp(sprintf('No RV points found. Current sector rotation is %0.5g',SET(no).SectorRotation)); return end @@ -566,7 +570,7 @@ function defineslices(sign,part) %#ok doepi = true; if isempty(SET(no).EpiX) doepi = false; -end; +end %Find sector rotation sectorrot = 0; %mean sector rotation @@ -579,7 +583,7 @@ function defineslices(sign,part) %#ok else x = SET(no).EndoX(:,SET(no).EDT,pos(loop)); y = SET(no).EndoY(:,SET(no).EDT,pos(loop)); - end; + end mx = mean(x); my = mean(y); @@ -589,8 +593,8 @@ function defineslices(sign,part) %#ok for rloop = 1:length(SET(no).Point.Z) if (isequal(SET(no).Point.Label{rloop},'RV insertion') || isequal(SET(no).Point.Label{rloop},'P2') || isequal(SET(no).Point.Label{rloop},'P1')) && isequal(pos(loop),SET(no).Point.Z(rloop)) ind = [ind rloop]; %#ok - end; - end; + end + end if length(ind) < 2 message = dprintf('Expected two insertion points, found %d.',length(ind)); @@ -611,7 +615,7 @@ function defineslices(sign,part) %#ok [ind1,ind2] = ind2sub([length(ind) length(ind)],largestdist); ind = sort([ind(ind1) ind(ind2)]); % return; - end; + end p1x = SET(no).Point.X(ind(1)); p1y = SET(no).Point.Y(ind(1)); @@ -638,7 +642,7 @@ function defineslices(sign,part) %#ok else xr = [x(indp2:end);x(1:indp1)]; yr = [y(indp2:end);y(1:indp1)]; - end; + end %Extract point x = xr(round(length(xr)/2)); @@ -659,10 +663,10 @@ function defineslices(sign,part) %#ok alpha = atan2(y-my,x-mx); alpha = alpha*180/pi; sectorrot = sectorrot-(90+alpha); %add all then divide -end; +end sectorrot = sectorrot/length(pos); -disp(dprintf('LV rotated %d degrees',round(sectorrot))); +disp(sprintf('LV rotated %d degrees',round(sectorrot))); SET(no).SectorRotation = sectorrot; %--------------------------------------- @@ -674,26 +678,29 @@ function defineslices(sign,part) %#ok gui = DATA.GUI.Bullseye; -v = get(gui.handles.rotationfromannotationcheckbox,'value'); -if v - pos = LVrotation('rotationfromannotationhelper',gui.no); - if isempty(pos) %No points for rotation found - set(gui.handles.rotationfromannotationcheckbox,'value',0) - end +pos = LVrotation('rotationfromannotationhelper',gui.no); +if isempty(pos) %No points for rotation found + return; end - %update slider set(gui.handles.rotationslider,'value',SET(gui.no).SectorRotation); %call to graphically update rotation & bullseye updatesliceimage; +updateplot; %------------------------------- function rotationslider_Callback %#ok %------------------------------- %Callback for rotation slider. Update slice image. +global DATA SET +gui = DATA.GUI.Bullseye; + updatesliceimage; +%Enable update button +set(gui.handles.updatepushbutton,'enable','on','BackgroundColor',[0.929 0.694 0.125],'ForegroundColor',[0 0 0]); + %--------------------------- function updatelongaxisimage @@ -730,9 +737,6 @@ function updatesliceimage(plotseperate) plotseperate = false; end -%Enable update button -set(gui.handles.updatepushbutton,'enable','on'); - tf = SET(gui.no).CurrentTimeFrame; SET(gui.no).SectorRotation = mygetvalue(gui.handles.rotationslider); @@ -786,7 +790,7 @@ function updatesliceimage(plotseperate) axis(ax,'image','off'); cmap = gray(256); colormap(ax,cmap); - title('LV rotation'); + title(dprintf('LV rotation')); end %Update longaxisimage @@ -797,19 +801,19 @@ function updatesliceimage(plotseperate) [endox,endoy] = calcfunctions('resamplemodel',SET(gui.no).EndoX(:,tf,gui.slice),SET(gui.no).EndoY(:,tf,gui.slice),DATA.Pref.RadialProfiles); if ~isempty(SET(gui.no).EpiX) [epix,epiy] = calcfunctions('resamplemodel',SET(gui.no).EpiX(:,tf,gui.slice), SET(gui.no).EpiY(:,tf,gui.slice),DATA.Pref.RadialProfiles); - end; + end else endox = SET(gui.no).EndoX(:,tf,gui.slice); endoy = SET(gui.no).EndoY(:,tf,gui.slice); if ~isempty(SET(gui.no).EpiX) epix = SET(gui.no).EpiX(:,tf,gui.slice); epiy = SET(gui.no).EpiY(:,tf,gui.slice); - end; -end; + end +end if isempty(SET(gui.no).EpiX) epix = NaN; epiy = NaN; -end; +end %Plot contours if ~plotseperate @@ -819,15 +823,15 @@ function updatesliceimage(plotseperate) set(gui.handles.endocontour,'linewidth','visible','off'); else set(gui.handles.endocontour,'linewidth',DATA.Pref.LineWidth); - end; + end if ~isempty(SET(gui.no).EpiX) gui.handles.epicontour = plot(gui.handles.imageaxes,epiy,epix,'g-'); if DATA.Pref.LineWidth==0 set(gui.handles.epicontour,'linewidth','visible','off'); else set(gui.handles.epicontour,'linewidth',DATA.Pref.LineWidth); - end; - end; + end + end else %plot in seperate window hold(ax,'on'); @@ -836,7 +840,7 @@ function updatesliceimage(plotseperate) if ~isempty(SET(gui.no).EpiX) epicontour = plot(ax,epiy,epix,'g-'); set(epicontour,'linewidth',DATA.Pref.LineWidth); - end; + end end @@ -865,16 +869,16 @@ function updatesliceimage(plotseperate) else h = plot(gui.handles.imageaxes,[min(imsize(2),max(1,gui.meany)) min(imsize(2),max(1,xpos))], ... [min(imsize(1),max(1,gui.meanx)) min(imsize(1),max(1,ypos))],'w-'); - end; + end if gui.numsectors>1 && gui.numsectors<=20 gui.handles.numtext{loop} = text(xposm,yposm,sprintf('%d',gui.numsectors+1-loop),'parent',gui.handles.imageaxes); set(gui.handles.numtext{loop},'color','y','fontsize',12); - end; + end if DATA.Pref.LineWidth==0 set(h,'linewidth','visible','off'); else set(h,'linewidth',DATA.Pref.LineWidth); - end; + end else %plot in seperate window if (loop==1) %Draw an extra long line @@ -882,7 +886,7 @@ function updatesliceimage(plotseperate) [min(imsize(1),max(1,gui.meanx)) min(imsize(1),max(1,1.5*ypos-0.5*gui.meany))],'y-'); set(h,'linewidth',DATA.Pref.LineWidth); end - end; + end end else @@ -909,16 +913,16 @@ function updatesliceimage(plotseperate) else gui.handles.line{loop} = plot(gui.handles.imageaxes,[min(imsize(2),max(1,gui.meany)) min(imsize(2),max(1,xpos))], ... [min(imsize(1),max(1,gui.meanx)) min(imsize(1),max(1,ypos))],'w-'); - end; + end if gui.numsectors>1 && gui.numsectors<=20 gui.handles.numtext{loop} = text(xposm,yposm,sprintf('%d',gui.numsectors+1-loop),'parent',gui.handles.imageaxes); set(gui.handles.numtext{loop},'color','y','fontsize',12); - end; + end if DATA.Pref.LineWidth==0 set(gui.handles.line{loop},'linewidth','visible','off'); else set(gui.handles.line{loop},'linewidth',DATA.Pref.LineWidth); - end; + end else %plot in seperate window if (loop==1) @@ -926,11 +930,11 @@ function updatesliceimage(plotseperate) line = plot(ax,[min(imsize(2),max(1,gui.meany)) min(imsize(2),max(1,1.5*xpos-0.5*gui.meany))], ... [min(imsize(1),max(1,gui.meanx)) min(imsize(1),max(1,1.5*ypos-0.5*gui.meanx))],'y-'); set(line,'linewidth',DATA.Pref.LineWidth); - end; + end end - end; -end; + end +end if ~plotseperate hold(gui.handles.imageaxes,'off'); else @@ -943,13 +947,11 @@ function updatesliceimage(plotseperate) %Properly close the GUI. global DATA - try - DATA.GUI.Bullseye=close(DATA.GUI.Bullseye); %close the flow gui -catch %#ok - delete(gcbf) + close(DATA.GUI.Bullseye); %close the flow gui +catch + close(gcbf); end - DATA.GUI.Bullseye= []; %----------------------- @@ -978,19 +980,19 @@ function updatesliceimage(plotseperate) [endox,endoy] = calcfunctions('resamplemodel',SET(gui.no).EndoX(:,tf,gui.slice),SET(gui.no).EndoY(:,tf,gui.slice),DATA.Pref.RadialProfiles); if ~isempty(SET(gui.no).EpiX) [epix,epiy] = calcfunctions('resamplemodel',SET(gui.no).EpiX(:,tf,gui.slice), SET(gui.no).EpiY(:,tf,gui.slice),DATA.Pref.RadialProfiles); - end; + end else endox = SET(gui.no).EndoX(:,tf,gui.slice); endoy = SET(gui.no).EndoY(:,tf,gui.slice); if ~isempty(SET(gui.no).EpiX) epix = SET(gui.no).EpiX(:,tf,gui.slice); epiy = SET(gui.no).EpiY(:,tf,gui.slice); - end; -end; + end +end if isempty(SET(gui.no).EpiX) epix = NaN; epiy = NaN; -end; +end %Plot contours hold on; @@ -999,7 +1001,7 @@ function updatesliceimage(plotseperate) set(h,'linewidth','visible','off'); else set(h,'linewidth',DATA.Pref.LineWidth); -end; +end if ~isempty(SET(gui.no).EpiX) h = plot(epiy,epix,'g-'); @@ -1007,8 +1009,8 @@ function updatesliceimage(plotseperate) set(h,'linewidth','visible','off'); else set(h,'linewidth',DATA.Pref.LineWidth); - end; -end; + end +end %Plot sectors hold on; @@ -1030,17 +1032,17 @@ function updatesliceimage(plotseperate) h = plot([gui.meany 1.5*xpos-0.5*gui.meany],[gui.meanx 1.5*ypos-0.5*gui.meany],'y-'); else h = plot([gui.meany xpos],[gui.meanx ypos],'y-'); - end; + end if DATA.Pref.LineWidth==0 set(h,'linewidth','visible','off'); else set(h,'linewidth',DATA.Pref.LineWidth); - end; + end if gui.numsectors<=20 h = text(xposm,yposm,sprintf('%d',gui.numsectors+1-loop)); set(h,'color','y','fontsize',12); - end; - end; + end + end else %--- Epi exists => draw both @@ -1060,18 +1062,18 @@ function updatesliceimage(plotseperate) h = plot([gui.meany 1.5*xpos-0.5*gui.meany],[gui.meanx 1.5*ypos-0.5*gui.meanx],'y-'); else h = plot([gui.meany xpos],[gui.meanx ypos],'y-'); - end; + end if DATA.Pref.LineWidth==0 set(h,'linewidth','visible','off'); else set(h,'linewidth',DATA.Pref.LineWidth); - end; + end if gui.numsectors<=20 h = text(xposm,yposm,sprintf('%d',gui.numsectors+1-loop)); set(h,'color','y','fontsize',12); - end; - end; -end; + end + end +end hold off; %---------------------------- @@ -1165,7 +1167,8 @@ function setdata(type,datain) gui = DATA.GUI.Bullseye; %Grey out update button -set(gui.handles.updatepushbutton,'enable','off'); +set(gui.handles.updatepushbutton,'enable','off',... + 'BackgroundColor',DATA.GUISettings.BackgroundColor,'ForegroundColor',DATA.GUISettings.ForegroundColor); %Get String temp = mygetlistbox(gui.handles.bullseyelistbox); @@ -1198,7 +1201,7 @@ function setdata(type,datain) outtf = []; engparameter = translation.dictionary(tempstri{temp},'English',DATA.Pref.Language); %ensure that it is English -switch lower(engparameter); +switch lower(engparameter) case 'maximal expansion velocity (temporal max)' radvel = calcfunctions('calcradialvelocity',gui.no); meanradvel = calcfunctions('findmeaninsector','endo',radvel,find(ind),gui.numsectors,gui.no); @@ -1243,7 +1246,7 @@ function setdata(type,datain) case 'fractional wallthickening' if isequal(SET(gui.no).EDT,SET(gui.no).EST) mywarning('Warning, end-diastole occurs at the same time as end-systole. Use autodetect under edit menu.',DATA.GUI.Segment); - end; + end wallthickness = calcfunctions('calcwallthickness',gui.numsectors,gui.no); outdata = (wallthickness(:,ind,SET(gui.no).EST)-wallthickness(:,ind,SET(gui.no).EDT))./wallthickness(:,ind,SET(gui.no).EDT); outdata = outdata*100; @@ -1297,9 +1300,9 @@ function setdata(type,datain) s.Epicardium_percent = 20; [s,ok] = inputstruct(s,'Selected coverage.'); if ~ok - myfailed('Aborted.'); +% myfailed('Aborted.'); return; - end; + end endo = s.Endocardium_percent/100; epi = s.Epicardium_percent/100; @@ -1325,10 +1328,10 @@ function setdata(type,datain) outtf = tf; case 'scar transmurality area based' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No infarct data available, use report myocardial intensity before.',DATA.GUI.Segment); return; - end; + end tf = SET(gui.no).CurrentTimeFrame; [~,outdata] = calcfunctions('calcintensityanddefect',SET(gui.no).IM,tf,DATA.Pref.RadialProfiles,gui.numsectors,DATA.Pref.RadialProfiles, ... find(ind),gui.no, ... @@ -1336,27 +1339,27 @@ function setdata(type,datain) [SET(gui.no).XSize SET(gui.no).YSize],[SET(gui.no).ResolutionX SET(gui.no).ResolutionY],SET(gui.no).Scar.Result,1,false); outunit = '%'; case 'scar transmurality line based' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No infarct data available, use report myocardial intensity before.',DATA.GUI.Segment); return; - end; + end tf = SET(gui.no).CurrentTimeFrame; outdata = viability('calctransmuralityline',gui.numsectors,gui.no); outunit = '%'; case 'max scar transmurality (spatial max)' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No infarct data available, use report myocardial intensity before.',DATA.GUI.Segment); return; - end; + end valuetype = 'max'; tf = SET(gui.no).CurrentTimeFrame; [~,outdata] = viability('calctransmuralityline',gui.numsectors,gui.no); outunit = '%'; case 'scar transmurality area based and myocardial intensity' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No Scar data available.',DATA.GUI.Segment); return; - end; + end tf = SET(gui.no).CurrentTimeFrame; outdata = calcfunctions('calcintensityanddefect',SET(gui.no).IM,tf,DATA.Pref.RadialProfiles,gui.numsectors,DATA.Pref.RadialProfiles, ... find(ind),gui.no,SET(gui.no).EndoX,SET(gui.no).EndoY,SET(gui.no).EpiX,SET(gui.no).EpiY, ... @@ -1383,16 +1386,16 @@ function setdata(type,datain) outdata = outdata.*defect; outunit = ''; case 'weighted infarct transmurality' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No Scar data available.',DATA.GUI.Segment); return; - end; + end %Call viabilityweight to get weighting of infarct tf = SET(gui.no).CurrentTimeFrame; [~,infarctweightmap] = viability('viabilityweight',gui.no); if isempty(infarctweightmap) infarctweightmap = ones(size(SET(gui.no).Scar.Result)); - end; + end meaninfarctweight = calcfunctions('calcintensityanddefect', ... infarctweightmap.*SET(gui.no).Scar.Result,tf,DATA.Pref.RadialProfiles, ... gui.numsectors,DATA.Pref.RadialProfiles,find(ind),gui.no, ... @@ -1402,10 +1405,10 @@ function setdata(type,datain) outdata = 100*meaninfarctweight; outunit = '%'; case 'grayzone transmurality area based' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No infarct data available, use report myocardial intensity before.',DATA.GUI.Segment); return; - end; + end mapsz = size(SET(gui.no).Scar.GreyZone.map); rescale = @(x)(0.5+mapsz(1)/SET(gui.no).XSize*(x-0.5)); im = zeros(mapsz); %imresize(SET(gui.no).IM,mapsz,'bilinear'); @@ -1417,10 +1420,10 @@ function setdata(type,datain) mapsz(1:2),[SET(gui.no).ResolutionX SET(gui.no).ResolutionY],SET(gui.no).Scar.GreyZone.map==1); outunit = '%'; case 'core transmurality area based' - if isempty(SET(gui.no).Scar); + if isempty(SET(gui.no).Scar) myfailed('No infarct data available, use report myocardial intensity before.',DATA.GUI.Segment); return; - end; + end mapsz = size(SET(gui.no).Scar.GreyZone.map); rescale = @(x)(0.5+mapsz(1)/SET(gui.no).XSize*(x-0.5)); im = zeros(mapsz); %imresize(SET(gui.no).IM,mapsz,'bilinear'); @@ -1432,10 +1435,10 @@ function setdata(type,datain) mapsz(1:2),[SET(gui.no).ResolutionX SET(gui.no).ResolutionY],SET(gui.no).Scar.GreyZone.map==2); outunit = '%'; case 'mar transmurality area based' - if isempty(SET(gui.no).MaR); + if isempty(SET(gui.no).MaR) myfailed('No MaR data available.',DATA.GUI.Segment); return; - end; + end tf = SET(gui.no).CurrentTimeFrame; [~,outdata] = calcfunctions('calcintensityanddefect',SET(gui.no).IM,tf,DATA.Pref.RadialProfiles,gui.numsectors,DATA.Pref.RadialProfiles, ... find(ind),gui.no, ... @@ -1444,29 +1447,29 @@ function setdata(type,datain) outunit = '%'; outtf = tf; case 'mar transmurality line based' - if isempty(SET(gui.no).MaR); + if isempty(SET(gui.no).MaR) myfailed('No MaR data available.',DATA.GUI.Segment); return; - end; + end tf = SET(gui.no).CurrentTimeFrame; outdata = mar('calctransmuralityline',gui.numsectors,gui.no); outunit = '%'; outtf = tf; case 'max mar transmurality (spatial max)' - if isempty(SET(gui.no).MaR); + if isempty(SET(gui.no).MaR) myfailed('No MaR data available.',DATA.GUI.Segment); return; - end; + end valuetype = 'max'; tf = SET(gui.no).CurrentTimeFrame; [~,outdata] = mar('calctransmuralityline',gui.numsectors,gui.no); outunit = '%'; outtf = tf; case 'mar transmurality area based and myocardial intensity' - if isempty(SET(gui.no).MaR); + if isempty(SET(gui.no).MaR) myfailed('No MaR data available.',DATA.GUI.Segment); return; - end; + end tf = SET(gui.no).CurrentTimeFrame; [outdata,defect] = calcfunctions('calcintensityanddefect',SET(gui.no).IM,tf,DATA.Pref.RadialProfiles,gui.numsectors,DATA.Pref.RadialProfiles, ... find(ind),gui.no, ... @@ -1499,23 +1502,23 @@ function setdata(type,datain) if not(ok) myfailed('Could not import clipboard data.',DATA.GUI.Segment); return; - end; + end tf = 1; outunit = ''; otherwise gui.parameter = ''; outunit = ''; -end; +end %Determine max and min value [maxv,ok] = str2num(mygetedit(gui.handles.maxedit)); %#ok if not(ok) || isempty(maxv) maxv = max(outdata(:)); -end; +end [minv,ok] = str2num(mygetedit(gui.handles.minedit)); %#ok if not(ok) || isempty(minv) minv = min(outdata(:)); -end; +end %Store gui.outdata = outdata; @@ -1523,20 +1526,24 @@ function setdata(type,datain) gui.outtf = outtf; %Find axes to plot in +isseparetewindow = false; if get(gui.handles.separatewindowcheckbox,'value') - figure(22); - set(22,'Name','Bulleseye plot','numbertitle','off'); + separatewindowfig = figure(22); + setupicon(separatewindowfig); + set(separatewindowfig,'Name','Bullseye plot','numbertitle','off'); + set(separatewindowfig,'Color',DATA.GUISettings.BackgroundColor); tempax = gca; + isseparetewindow = true; else tempax = gui.handles.bullseyeaxes; -end; +end %get number of points in image [n,ok] = str2num(mygetedit(gui.handles.nedit)); %#ok if not(ok) mywarning('Not a valid number for n.',DATA.GUI.Segment); n = 200; -end; +end %Determine if smooth bulleye version or not. gui.ahaoutdata = []; @@ -1550,28 +1557,31 @@ function setdata(type,datain) [maxv,ok] = str2num(mygetedit(gui.handles.maxedit)); %#ok if not(ok) maxv = max(gui.ahaoutdata(:)); - end; + end [minv,ok] = str2num(mygetedit(gui.handles.minedit)); %#ok if not(ok) minv = min(gui.ahaoutdata(:)); - end; -end; + end +end %Adjust max/min if ~isempty(minv) && ~isempty(maxv) && not(isnan(minv)) && not(isnan(maxv)) && (maxv>minv) set(tempax,'clim',[minv maxv]); -end; +end %Add title if isempty(gui.outunit) && isempty(gui.outtf) - title(tempax,sprintf('%s',gui.parameter)); + title(tempax,sprintf('%s',gui.parameter),'Color',DATA.GUISettings.ForegroundColor); elseif isempty(gui.outunit) && ~isempty(gui.outtf) - title(tempax,sprintf('%s in time frame %d',gui.parameter,gui.outtf)); + title(tempax,dprintf('%s in time frame %d',gui.parameter,gui.outtf),'Color',DATA.GUISettings.ForegroundColor); elseif ~isempty(gui.outunit) && isempty(gui.outtf) - title(tempax,sprintf('%s [%s]',gui.parameter,gui.outunit)); + title(tempax,sprintf('%s [%s]',gui.parameter,gui.outunit),'Color',DATA.GUISettings.ForegroundColor); else - title(tempax,sprintf('%s [%s] in time frame %d',gui.parameter,gui.outunit,gui.outtf)); -end; + title(tempax,dprintf('%s [%s] in time frame %d',gui.parameter,gui.outunit,gui.outtf),'Color',DATA.GUISettings.ForegroundColor); +end +if isseparetewindow + tempax.Title.FontSize = 14; +end %Colormap v = mygetlistbox(gui.handles.colormaplistbox); @@ -1586,16 +1596,21 @@ function setdata(type,datain) cmap = spect(256); case 5 cmap = gray(256); -end; +end if get(gui.handles.invertcolorscheckbox,'value') cmap = flipud(cmap); -end; +end colormap(tempax,cmap); %Add colorbar gui.handles.colorbar = colorbar('peer',tempax); +if isseparetewindow + gui.handles.colorbar.LineWidth = 1.0; + gui.handles.colorbar.FontSize = 12; +end +set(gui.handles.colorbar,'Color',DATA.GUISettings.ForegroundColor); %---------------------------- @@ -1607,7 +1622,7 @@ function setdata(type,datain) gui.slice = SET(gui.no).ZSize-round(mygetvalue(gui.handles.sliceslider))+1; set(gui.handles.sliceslider,'Value',round(mygetvalue(gui.handles.sliceslider))); -set(gui.handles.slicetext,'String',sprintf('Slice %d',gui.slice)); +set(gui.handles.slicetext,'String',dprintf('Slice %d',gui.slice)); updatesliceimage; updatelongaxisimage if 0%mygetvalue(gui.handles.thissliceonlycheckbox) @@ -1632,7 +1647,7 @@ function setdata(type,datain) if nargin<4 valuetype = 'mean'; %default; -end; +end if nargin<5 linetype='w-'; @@ -1649,7 +1664,7 @@ function setdata(type,datain) if size(m,1)~=24 myfailed('Expected 24 sectors as input size.',DATA.GUI.Segment); return; - end; + end %Reshape the transmurality by replicating each slice into three numslices = size(m,2); @@ -1722,14 +1737,14 @@ function setdata(type,datain) temp=max(reshape(temp(:),[6 4]),[],1); v = [v;temp(:)]; %Add apical slices v = [v;max(m(:,1))]; %apex - end; -end; %End of v calculation + end +end %End of v calculation doplot = true; if (nargin<2)||isempty(ax) doplot = false; -end; +end %Unpack vector to matrix m = zeros(12,4); @@ -1772,7 +1787,7 @@ function setdata(type,datain) im = m(idx); im(rad>(numslices+1)) = NaN; %im = rad; -end; +end if doplot scale = n/(numslices+1); @@ -1792,7 +1807,7 @@ function setdata(type,datain) for loop=1:(numslices+1) h = plot(ax,n+1+scale*loop*xc,n+1+scale*loop*yc,linetype); set(h,'linewidth',2); - end; + end hold(ax,'off'); %Draw lines @@ -1813,16 +1828,16 @@ function setdata(type,datain) h = plot(ax,scale*[4+4*a 4+2*a],scale*[4+4*b 4+2*b],linetype); set(h,'linewidth',2); h = plot(ax,scale*[4+4*a 4+2*a],scale*[4-4*b 4-2*b],linetype); set(h,'linewidth',2); hold(ax,'off'); -end; +end %returns value if necessary. if nargout>0 varargout{1} = v; -end; +end if nargout>1 varargout{2} = im; -end; +end %--------------------------------------------------- function [varargout] = bullseye2(m,ax,n,flipx,vc,no) @@ -1859,7 +1874,7 @@ function setdata(type,datain) if size(m,2) < minnbrsectors m = imresize(repmat(m,1,3),minnbrsectors,'bilinear'); m = m(1:minnbrsectors:end,size(m,2)/3+1:2*size(m,2)/3); -end; +end %Determine size sectors = size(m,2); @@ -1929,7 +1944,7 @@ function setdata(type,datain) if flipx im = fliplr(im); -end; +end if nargout==0 h = imagesc(im,'parent',ax); @@ -1937,7 +1952,7 @@ function setdata(type,datain) axis(ax,'image','off'); else varargout{1} = im; -end; +end %----------------------------------- function im = bullseye(m,ax,n,vc,no,tf) @@ -2065,7 +2080,7 @@ function setdata(type,datain) h = plot(ax,n+1+scale*loop*xc,n+1+scale*loop*yc,'w-'); end set(h,'linewidth',2); - end; + end hold(ax,'off'); %Label sectors @@ -2076,6 +2091,6 @@ function setdata(type,datain) h = text(n+1+scale*1.5*cos(omega(loop)),... n+1+scale*1.5*sin(omega(loop)),sprintf('%d',sectors+1-loop),'parent',ax); set(h,'color',[1 1 1]) - end; + end hold(ax,'off'); end diff --git a/source/reportflow.m b/source/reportflow.m index 029658c..38c9b99 100644 --- a/source/reportflow.m +++ b/source/reportflow.m @@ -19,7 +19,7 @@ [temp,ok] = str2num(mygetedit(gui.handles.resampedit)); %#ok if not(ok) - mydisp('Unknown value'); + disp('Illegal value'); else gui.resampsize = temp; end @@ -48,7 +48,7 @@ if ~isempty(gui.resampsize) TSize2 = gui.resampsize; else - mydisp('TSize2 error'); + disp('TSize2 error'); TSize2 = 5; end @@ -107,7 +107,7 @@ gui.diameter = 2*10*sqrt(gui.area/pi); %mm*10 => cm nom = SET(no).Flow.MagnitudeNo; -nop = SET(no).Flow.PhaseNo; + %backup variables: gui.TIncr = ((SET(nom).TSize-1)*SET(nom).TIncr)/(TSize2-1); gui.tsize = TSize2; @@ -116,11 +116,10 @@ recalculate(no); %Also do an update % gui.resamped = 0; -DATA.updateaxestables('flow',nom,nop); %maybe unnecessary? - +segment('updateflow'); %DATA.updateaxestables('flow',nom,nop); %maybe unnecessary? %--------------------------------- -function ok = init(no,eddycheck) +function ok = init(no,eddycheck, invisible) %--------------------------------- %Init flow report GUI global DATA SET NO @@ -132,57 +131,58 @@ if nargin<2 eddycheck = true; -end; +end +if nargin<3 + invisible = false; +end -set(DATA.Handles.reportflowicon,'state','off'); if isempty(SET(no).Flow) myfailed('No flow data in current image stack.',DATA.GUI.Segment); return; -end; +end if ~isempty(SET(no).Flow) nom = SET(no).Flow.MagnitudeNo; else return; -end; +end if isempty(SET(nom).Flow.PhaseNo) myfailed('No through plane velocity data found.',DATA.GUI.Segment); return; -end; +end if SET(nom).RoiN==0 myfailed('No ROIs available.',DATA.GUI.Segment); return; -end; +end tempnos=[SET(no).Flow.MagnitudeNo SET(no).Flow.PhaseNo]; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants if not(imissingle) + disp('non single image') return; end if ~DATA.Silent - panel = find(DATA.ViewPanels==nom); - if ~isempty(panel) - panel = panel(1); - - DATA.switchtoimagestack(nom); - segment('switchtopanel',panel); - end; -end; + viewfunctions('switchimagestack',nom) +end if isempty(SET(nom).EndAnalysis) SET(nom).EndAnalysis = SET(nom).TSize; -end; +end if isempty(SET(nom).StartAnalysis) SET(nom).StartAnalysis = 1; -end; +end if (SET(nom).EndAnalysis-SET(nom).StartAnalysis) ==0 - if ~isopengui('flowonetimephase.fig'); - gui = mygui('flowonetimephase.fig'); + if ~isopengui('flowonetimephase.fig') + if invisible + gui = mygui('flowonetimephase.fig','invisible'); + else + gui = mygui('flowonetimephase.fig'); + end DATA.GUI.Flow = gui; else gui = DATA.GUI.Flow; @@ -196,14 +196,13 @@ %More than one timeframe rois2take = [rois2take loop]; %#ok % end; -end; +end gui.rois2take = rois2take; gui.numrois = length(rois2take); gui.nom = nom; %gui.nop = nop; showflowroidata(no,0); - %% elseif (SET(nom).EndAnalysis-SET(nom).StartAnalysis)<0 %1 myfailed('No timespan, adjust Start/End analysis time (under stress menu or drag red bar).',DATA.GUI.Segment); return; @@ -214,7 +213,7 @@ 'supported for flow calculations. Will use mean time step.'],... 'Accept for now',... 'Accept and apply to stack',... - 'Cancel'); + 'Cancel') case 2 SET(nom).TimeVector = SET(nom).TIncr*(0:SET(nom).TSize-1); SET(nop).TimeVector = SET(nom).TimeVector; @@ -235,29 +234,37 @@ plotonok = true; floweddycurrent('initsmall',plotonok); %When specifying plotonok, then this function is called again when user press ok. return; - end; + end catch %Do point of crasch if we can't perform - end; - end; + end + end end -end; - -%Open GUI +end +%Calculate number of ROI's +rois2take = []; +for loop=1:SET(nom).RoiN + if sum(~isnan(SET(nom).Roi(loop).X(1,:)))>1 + %More than one timeframe + rois2take = [rois2take loop]; %#ok + end +end +if isempty(rois2take) + return +end -if ~isopengui('flow.fig'); - gui = mygui('flow.fig'); +%Open GUI +if ~isopengui('flow.fig') + if invisible + gui = mygui('flow.fig','invisible'); + else + gui = mygui('flow.fig'); + end DATA.GUI.Flow = gui; else gui = DATA.GUI.Flow; end -% -% load('pointers.mat'); -% myset(DATA.imagefig,... -% 'pointer','custom',... -% 'pointershapecdata',1+pointer.point,... -% 'pointershapehotspot',[7 7]); -set(gui.fig,'Name',translation.dictionary('Flow report')); +set(gui.fig,'Name',dprintf('Flow report')); gui.outsize = [SET(nom).XSize SET(nom).YSize]; if not(isfield(SET(nom).Flow,'HeartRate')) || isempty(SET(nom).Flow.HeartRate) @@ -267,16 +274,14 @@ else SET(nom).Flow.HeartRate = temphr; end - DATA.flowreportupdate; %update result panel + segment('updateflow'); %update result panel end gui.hr = SET(nom).Flow.HeartRate; set(gui.handles.heartratetext,'String',dprintf('Heart rate: %0.3g [bpm]',gui.hr)); -DATA.initreportflow(gui.handles); - if not(isfield(SET(nop).Flow,'PhaseCorr')) SET(nop).Flow.PhaseCorr = []; -end; +end gui.t = SET(nom).TIncr*(-1+(1:SET(nom).TSize)); @@ -286,14 +291,17 @@ gui.nom = nom; gui.nop = nop; -%Calculate number of ROI's -rois2take = []; -for loop=1:SET(nom).RoiN - if sum(~isnan(SET(nom).Roi(loop).X(1,:)))>1 - %More than one timeframe - rois2take = [rois2take loop]; %#ok - end; -end; +% % % %Calculate number of ROI's +% % % rois2take = []; +% % % for loop=1:SET(nom).RoiN +% % % if sum(~isnan(SET(nom).Roi(loop).X(1,:)))>1 +% % % %More than one timeframe +% % % rois2take = [rois2take loop]; %#ok +% % % end +% % % end +% % % if isempty(rois2take) +% % % return +% % % end gui.rois2take = rois2take; gui.numrois = length(rois2take); @@ -322,7 +330,11 @@ function defineheartrate(no) temphr = (60/(SET(no).TSize*SET(no).TIncr)); %assume real time flow, aks user to define number of hearts beat -nbrheartbeats = mygetnumber('Enter number of heart beats (decimal with .)','Heart beats',1.0,0,[]); +[nbrheartbeats,ok] = mygetnumber('Enter number of heart beats (decimal with .)', 'Heart beats',1.0,0,[]); +if not(ok) + myfailed('Invalid number of heart beats or aborted.'); + return; +end if ~isempty(nbrheartbeats) && nbrheartbeats > 0 && isnumeric(nbrheartbeats) SET(no).Flow.HeartRate = nbrheartbeats*temphr; else @@ -332,7 +344,7 @@ function defineheartrate(no) mymsgbox(dprintf('The heart rate is now set to %0.3g',SET(no).Flow.HeartRate),'Heart rate',DATA.GUI.Segment); if nargin < 1 - DATA.flowreportupdate; %update result panel + segment('updateflow'); %update result panel end %----------------------- @@ -349,62 +361,65 @@ function showflowroidata(no,flag) numrois = gui.numrois; %SET(no).Flow.Result(roinbr) - +if isempty(SET(no).Flow.Result) + close_Callback + return +end if flag == 0 -%Calculate Flow -gui.netflow = zeros(1,numrois); -gui.posflow = zeros(1,numrois); -gui.negflow = zeros(1,numrois); -gui.velmean = zeros(1,numrois); -gui.velstd = zeros(1,numrois); -gui.velmax = zeros(1,numrois); -gui.velmin = zeros(1,numrois); -gui.roiname = cell(1,numrois); -gui.roinbr = zeros(1,numrois); -gui.kenergy=0; -gui.area=zeros(1,numrois); -gui.volstri = dprintf('Roi-Name\tTotal vol\tForward vol\tBackward vol\n'); - -line = 3; -for rloop=1:numrois - %--- Interpolate up - - %Sum - gui.netflow(rloop) = SET(no).Flow.Result(rloop).netflow; - gui.posflow(rloop) = SET(no).Flow.Result(rloop).posflow; - gui.negflow(rloop) = SET(no).Flow.Result(rloop).negflow; - gui.velmean(rloop) = SET(no).Flow.Result(rloop).velmean; - gui.velstd(rloop) = SET(no).Flow.Result(rloop).velstd; - - gui.velmax(rloop) = SET(no).Flow.Result(rloop).velmax; - gui.velmin(rloop) = SET(no).Flow.Result(rloop).velmean; - gui.area(rloop) =SET(no).Flow.Result(rloop).area; + %Calculate Flow + gui.netflow = zeros(1,numrois); + gui.posflow = zeros(1,numrois); + gui.negflow = zeros(1,numrois); + gui.velmean = zeros(1,numrois); + gui.velstd = zeros(1,numrois); + gui.velmax = zeros(1,numrois); + gui.velmin = zeros(1,numrois); + gui.roiname = cell(1,numrois); + gui.roinbr = zeros(1,numrois); + gui.kenergy=0; + gui.area=zeros(1,numrois); + gui.volstri = dprintf('Roi-Name\tTotal vol\tForward vol\tBackward vol\n'); - %Add to stri - gui.volstri = [gui.volstri sprintf('%s\t%0.4g\t%0.4g\t%0.4g\n',... - SET(nom).Roi(rois2take(rloop)).Name,... - gui.netflow(rloop),... - gui.posflow(rloop),... - gui.negflow(rloop))]; -% gui.voltext = [gui.voltext dprintf('ROI: %s:\nNet: %0.3g ml\nNet: %0.3g l/min\nForward: %0.3g ml\nBackward: %0.3g ml\nRegurgitant fraction: %0.3g%%\n\n',... -% SET(nom).Roi(rois2take(rloop)).Name,... -% gui.nettotvol(rloop),... -% gui.nettotvol(rloop)*gui.hr/1000,... -% gui.netforwardvol(rloop),... -% gui.netbackwardvol(rloop),... -% abs(100*gui.netbackwardvol(rloop)/gui.netforwardvol(rloop)))]; - gui.voltext{line} = dprintf('ROI: %s:',SET(nom).Roi(rois2take(rloop)).Name); - gui.voltext{line+1} = dprintf('Net Flow: %0.3g ml/s',gui.netflow(rloop)); - gui.voltext{line+2} = dprintf('Pos Flow: %0.3g ml/s',gui.posflow(rloop)); - gui.voltext{line+3} = dprintf('Neg Flow: %0.3g ml/s',gui.negflow(rloop)); - gui.voltext{line+4} = dprintf('Mean Vel: %0.3g cm/s',gui.velmean(rloop)); - gui.voltext{line+5} = dprintf('Std Vel: %0.3g cm/s',gui.velstd(rloop)); - gui.voltext{line+6} = dprintf('Max Vel: %0.3g cm/s',gui.velmax(rloop)); - gui.voltext{line+7} = dprintf('Min Vel: %0.3g cm/s',gui.velmin(rloop)); -gui.voltext{line+8} = dprintf('ROI Area: %0.3g cm^2',gui.area(rloop)); - line = line+10; -end; + line = 3; + for rloop=1:numrois + %--- Interpolate up + + %Sum + gui.netflow(rloop) = SET(no).Flow.Result(rloop).netflow; + gui.posflow(rloop) = SET(no).Flow.Result(rloop).posflow; + gui.negflow(rloop) = SET(no).Flow.Result(rloop).negflow; + gui.velmean(rloop) = SET(no).Flow.Result(rloop).velmean; + gui.velstd(rloop) = SET(no).Flow.Result(rloop).velstd; + + gui.velmax(rloop) = SET(no).Flow.Result(rloop).velmax; + gui.velmin(rloop) = SET(no).Flow.Result(rloop).velmean; + gui.area(rloop) =SET(no).Flow.Result(rloop).area; + + %Add to stri + gui.volstri = [gui.volstri sprintf('%s\t%0.4g\t%0.4g\t%0.4g\n',... + SET(nom).Roi(rois2take(rloop)).Name,... + gui.netflow(rloop),... + gui.posflow(rloop),... + gui.negflow(rloop))]; + % gui.voltext = [gui.voltext dprintf('ROI: %s:\nNet: %0.3g ml\nNet: %0.3g l/min\nForward: %0.3g ml\nBackward: %0.3g ml\nRegurgitant fraction: %0.3g%%\n\n',... + % SET(nom).Roi(rois2take(rloop)).Name,... + % gui.nettotvol(rloop),... + % gui.nettotvol(rloop)*gui.hr/1000,... + % gui.netforwardvol(rloop),... + % gui.netbackwardvol(rloop),... + % abs(100*gui.netbackwardvol(rloop)/gui.netforwardvol(rloop)))]; + gui.voltext{line} = dprintf('ROI: %s:',SET(nom).Roi(rois2take(rloop)).Name); + gui.voltext{line+1} = dprintf('Net Flow: %0.3g ml/s',gui.netflow(rloop)); + gui.voltext{line+2} = dprintf('Pos Flow: %0.3g ml/s',gui.posflow(rloop)); + gui.voltext{line+3} = dprintf('Neg Flow: %0.3g ml/s',gui.negflow(rloop)); + gui.voltext{line+4} = dprintf('Mean Vel: %0.3g cm/s',gui.velmean(rloop)); + gui.voltext{line+5} = dprintf('Std Vel: %0.3g cm/s',gui.velstd(rloop)); + gui.voltext{line+6} = dprintf('Max Vel: %0.3g cm/s',gui.velmax(rloop)); + gui.voltext{line+7} = dprintf('Min Vel: %0.3g cm/s',gui.velmin(rloop)); + gui.voltext{line+8} = dprintf('ROI Area: %0.3g cm^2',gui.area(rloop)); + line = line+10; + end else line = 3; for rloop=1:numrois @@ -449,6 +464,22 @@ function recalculate(no) gui = DATA.GUI.Flow; nom = gui.nom; nop = gui.nop; +if gui.rois2take ~= SET(nom).RoiN + % Check if the number of time resolvedof ROIs has been updated outside the figure + rois2take = []; + for loop = 1:SET(nom).RoiN + if sum(~isnan(SET(nom).Roi(loop).X(1,:)))>1 + %More than one timeframe + rois2take = [rois2take loop]; %#ok + end + end + if ~isempty(rois2take) + gui.rois2take = rois2take; + gui.numrois = length(rois2take); + else + return + end +end rois2take = gui.rois2take; numrois = gui.numrois; @@ -465,99 +496,99 @@ function recalculate(no) gui.netflow = gui.velmean; gui.posflow = gui.velmean; gui.negflow = gui.velmean; - gui.phasecorrstring = ''; - if ~isempty(SET(nop).Flow.PhaseCorr) - if ~isfield(SET(nop).Flow,'PhaseCorrTimeResolved') - mywarning('Incompatible eddy current correction. Correction reset.',DATA.GUI.Segment); - SET(nop).Flow.PhaseCorr = []; - gui.phasecorrstring = ''; - else - if SET(nop).Flow.PhaseCorrTimeResolved - gui.phasecorrstring = '[Time-resolved eddy current compensation applied]'; - else - gui.phasecorrstring = '[Stationary eddy current compensation applied]'; - end; - end; - end; - warnedempty = false; - h = mywaitbarstart(numrois,'Please wait, calculating flow.'); - for rloop = 1:numrois - for tloop = SET(nom).Roi(rois2take(rloop)).T - %Create mask - mask = logical(segment('createmask',... - gui.outsize,... - SET(nom).Roi(rois2take(rloop)).Y(:,tloop),... - SET(nom).Roi(rois2take(rloop)).X(:,tloop))); - - %Extract phase image - temp = SET(nop).IM(:,:,tloop,SET(nom).Roi(rois2take(rloop)).Z); - - %If empty phasecorr, the do not add phase correction. - if isempty(SET(nop).Flow.PhaseCorr) - veldata = SET(nom).Roi(rois2take(rloop)).Sign*... - (temp-0.5)*2*SET(nop).VENC; - else - %Phase correction - if SET(nop).Flow.PhaseCorrTimeResolved - %Time resolved phase correction - veldata = SET(nom).Roi(rois2take(rloop)).Sign*... - (temp-0.5-SET(nop).Flow.PhaseCorr(:,:,tloop,SET(nom).Roi(rois2take(rloop)).Z))*2*SET(nop).VENC; - else - %Stationary phase correction - veldata = SET(nom).Roi(rois2take(rloop)).Sign*... - (temp-0.5-SET(nop).Flow.PhaseCorr(:,:,1,SET(nom).Roi(rois2take(rloop)).Z))*2*SET(nop).VENC; - end; - end; - - veldata = veldata(mask); - if isempty(veldata) - if not(warnedempty) - mywarning('Empty ROI detected. Should not occur.',DATA.GUI.Segment); - end; - warnedempty = true; - else - %Okej to go - posveldata = veldata(veldata>0); - negveldata = veldata(veldata<0); - gui.velmean(tloop,rloop) = mean(veldata); - gui.velstd(tloop,rloop) = std(veldata); - gui.velmax(tloop,rloop) = max(veldata); - gui.velmin(tloop,rloop) = min(veldata); - gui.kenergy(tloop,rloop) = sum((veldata/100).^3/2*(SET(nom).ResolutionX*SET(nom).ResolutionY/1e6)*1060); %kg/m^3 - gui.area(tloop,rloop) = SET(nom).ResolutionX*SET(nom).ResolutionY*sum(mask(:))/100; %cm^2 - gui.netflow(tloop,rloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(veldata); %cm^3 - gui.posflow(tloop,rloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(posveldata); %cm^3 - gui.negflow(tloop,rloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(negveldata); %cm^3 - end; - - end; - h = mywaitbarupdate(h); - end; - mywaitbarclose(h); - - - timeframes = SET(nom).StartAnalysis:SET(nom).EndAnalysis; - %Calculate diameter equivalent - gui.diameter = 2*10*sqrt(gui.area/pi); %mm*10 => cm - TIncr = SET(nom).TIncr; - TSize = SET(nom).TSize; + gui.phasecorrstring = ''; + if ~isempty(SET(nop).Flow.PhaseCorr) + if ~isfield(SET(nop).Flow,'PhaseCorrTimeResolved') + mywarning('Incompatible eddy current correction. Correction reset.',DATA.GUI.Segment); + SET(nop).Flow.PhaseCorr = []; + gui.phasecorrstring = ''; + else + if SET(nop).Flow.PhaseCorrTimeResolved + gui.phasecorrstring = dprintf('[Time-resolved eddy current compensation applied]'); + else + gui.phasecorrstring = dprintf('[Stationary eddy current compensation applied]'); + end + end + end + warnedempty = false; + h = mywaitbarstart(numrois,'Please wait, calculating flow.'); + for rloop = 1:numrois + for tloop = SET(nom).Roi(rois2take(rloop)).T + %Create mask + mask = logical(segment('createmask',... + gui.outsize,... + SET(nom).Roi(rois2take(rloop)).Y(:,tloop),... + SET(nom).Roi(rois2take(rloop)).X(:,tloop))); + + %Extract phase image + temp = SET(nop).IM(:,:,tloop,SET(nom).Roi(rois2take(rloop)).Z); + + %If empty phasecorr, the do not add phase correction. + if isempty(SET(nop).Flow.PhaseCorr) + veldata = SET(nom).Roi(rois2take(rloop)).Sign*... + (temp-0.5)*2*SET(nop).VENC; + else + %Phase correction + if SET(nop).Flow.PhaseCorrTimeResolved + %Time resolved phase correction + veldata = SET(nom).Roi(rois2take(rloop)).Sign*... + (temp-0.5-SET(nop).Flow.PhaseCorr(:,:,tloop,SET(nom).Roi(rois2take(rloop)).Z))*2*SET(nop).VENC; + else + %Stationary phase correction + veldata = SET(nom).Roi(rois2take(rloop)).Sign*... + (temp-0.5-SET(nop).Flow.PhaseCorr(:,:,1,SET(nom).Roi(rois2take(rloop)).Z))*2*SET(nop).VENC; + end + end + + veldata = veldata(mask); + if isempty(veldata) + if not(warnedempty) + mywarning('Empty ROI detected. Should not occur.',DATA.GUI.Segment); + end + warnedempty = true; + else + %Okej to go + posveldata = veldata(veldata>0); + negveldata = veldata(veldata<0); + gui.velmean(tloop,rloop) = mean(veldata); + gui.velstd(tloop,rloop) = std(veldata); + gui.velmax(tloop,rloop) = max(veldata); + gui.velmin(tloop,rloop) = min(veldata); + gui.kenergy(tloop,rloop) = sum((veldata/100).^3/2*(SET(nom).ResolutionX*SET(nom).ResolutionY/1e6)*1060); %kg/m^3 + gui.area(tloop,rloop) = SET(nom).ResolutionX*SET(nom).ResolutionY*sum(mask(:))/100; %cm^2 + gui.netflow(tloop,rloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(veldata); %cm^3 + gui.posflow(tloop,rloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(posveldata); %cm^3 + gui.negflow(tloop,rloop) = (10/1000)*SET(nom).ResolutionX*SET(nom).ResolutionY*sum(negveldata); %cm^3 + end + + end + h = mywaitbarupdate(h); + end + mywaitbarclose(h); + + + timeframes = SET(nom).StartAnalysis:SET(nom).EndAnalysis; + %Calculate diameter equivalent + gui.diameter = 2*10*sqrt(gui.area/pi); %mm*10 => cm + TIncr = SET(nom).TIncr; + TSize = SET(nom).TSize; else - gui.phasecorrstring = ''; -% StartAnalysis = 1; -% EndAnalysis = length(gui.t); - timeframes = 1:gui.tsize; - TIncr = gui.TIncr; - TSize = gui.tsize; + gui.phasecorrstring = ''; + % StartAnalysis = 1; + % EndAnalysis = length(gui.t); + timeframes = 1:gui.tsize; + TIncr = gui.TIncr; + TSize = gui.tsize; end if (isempty(TIncr) || isempty(TSize)) - mydisp('TIncr or TSize structures are empty due to resampling error or bad SET!'); + disp('TIncr or TSize structures are empty due to resampling error or bad SET!'); end - + gui.volstri = dprintf('Roi-Name\tTotal vol\tForward vol\tBackward vol\n'); gui.voltext{1} = dprintf('Time between green bars:%d ms\n\n',... - round(1000*TIncr*(length(timeframes)-1))); + round(1000*TIncr*(length(timeframes)-1))); %-------------------------------------------------------------------------- %Calculate stroke volume @@ -597,24 +628,26 @@ function recalculate(no) SET(nom).Roi(rois2take(rloop)).Name,... gui.nettotvol(rloop),... gui.netforwardvol(rloop),... - gui.netbackwardvol(rloop))]; -% gui.voltext = [gui.voltext dprintf('ROI: %s:\nNet: %0.3g ml\nNet: %0.3g l/min\nForward: %0.3g ml\nBackward: %0.3g ml\nRegurgitant fraction: %0.3g%%\n\n',... -% SET(nom).Roi(rois2take(rloop)).Name,... -% gui.nettotvol(rloop),... -% gui.nettotvol(rloop)*gui.hr/1000,... -% gui.netforwardvol(rloop),... -% gui.netbackwardvol(rloop),... -% abs(100*gui.netbackwardvol(rloop)/gui.netforwardvol(rloop)))]; + gui.netbackwardvol(rloop))]; + % gui.voltext = [gui.voltext dprintf('ROI: %s:\nNet: %0.3g ml\nNet: %0.3g l/min\nForward: %0.3g ml\nBackward: %0.3g ml\nRegurgitant fraction: %0.3g%%\n\n',... + % SET(nom).Roi(rois2take(rloop)).Name,... + % gui.nettotvol(rloop),... + % gui.nettotvol(rloop)*gui.hr/1000,... + % gui.netforwardvol(rloop),... + % gui.netbackwardvol(rloop),... + % abs(100*gui.netbackwardvol(rloop)/gui.netforwardvol(rloop)))]; gui.voltext{line} = dprintf('ROI: %s:',SET(nom).Roi(rois2take(rloop)).Name); - gui.voltext{line+1} = dprintf('Net: %0.3g ml',gui.nettotvol(rloop)); - gui.voltext{line+2} = dprintf('Net: %0.3g l/min',gui.nettotvol(rloop)*gui.hr/1000); - gui.voltext{line+3} = dprintf('Forward: %0.3g ml',gui.netforwardvol(rloop)); - gui.voltext{line+4} = dprintf('Backward: %0.3g ml',gui.netbackwardvol(rloop)); - gui.voltext{line+5} = dprintf('Regurgitant fraction: %0.3g%%',abs(100*gui.netbackwardvol(rloop)/gui.netforwardvol(rloop))); + gui.voltext{line+1} = dprintf('Net vol: %0.3g ml',gui.nettotvol(rloop)); + gui.voltext{line+2} = dprintf('Forward: %0.3g ml',gui.netforwardvol(rloop)); + gui.voltext{line+3} = dprintf('Backward: %0.3g ml',gui.netbackwardvol(rloop)); + gui.voltext{line+4} = dprintf('Regurgitant fraction: %0.3g%%',abs(100*gui.netbackwardvol(rloop)/gui.netforwardvol(rloop))); + gui.voltext{line+5} = dprintf('FlowCO: %0.3g l/min',gui.nettotvol(rloop)*gui.hr/1000); + line = line+7; -end; +end set(gui.handles.volumelistbox,'String',gui.voltext); +set(gui.fig,'pointer','arrow'); update(nom); %Also do an update exporttosetstruct; @@ -622,10 +655,14 @@ function recalculate(no) SET(nom).RoiCurrent = loop; calcfunctions('calcflow',nom); end -DATA.updateaxestables('flow',nom,nop); +segment('updateflow'); %DATA.updateaxestables('flow',nom,nop); + +grid(gui.handles.plotaxes,'on'); +gui.handles.plotaxes.GridColor = 'k'; +set(gui.handles.plotaxes,'Color',[0.94 0.94 0.94]); %--------------------- -function zoom_Callback +function zoom_Callback %#ok %--------------------- %Callback for checkbox toggling zoom on/off global DATA @@ -731,14 +768,14 @@ function recalculate(no) name = removeforbiddenchars(SET(1).PatientInfo.Name); if isempty(name) name = 'Hidden'; - end; + end else name = SET(1).Report.Name; end imwrite(im,fullfile(DATA.Pref.Pacs.ReportsheetPath,name,sprintf('flowaxes_%d.png',no))); %---------------------- -function close_Callback %#ok +function close_Callback %----------------------- %Close flow report GUI global DATA @@ -750,7 +787,7 @@ function recalculate(no) end DATA.GUI.Flow = []; -DATA.updateaxestables('flow'); +segment('updateflow'); %DATA.updateaxestables('flow'); %-------------- function update(no) @@ -776,8 +813,7 @@ function update(no) %reportflow('init'); end -s=get(gui.handles.parameterlistbox,'String'); -v=mygetlistbox(gui.handles.parameterlistbox); +v = mygetlistbox(gui.handles.parameterlistbox); switch v case 1 %'Flow' %--- Plot flow @@ -787,13 +823,15 @@ function update(no) for loop=2:size(gui.netflow,2) h = plot(gui.handles.plotaxes,t*1000,gui.netflow(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); - title(gui.handles.plotaxes,dprintf('Net flow. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Flow [ml/s]')); + title(gui.handles.plotaxes,dprintf('Net flow. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Flow [ml/s]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); + case 2 %'Positive/Negative Flow' %--- plot forward/backward flow h = plot(gui.handles.plotaxes,t*1000,gui.posflow(:,1),[d SET(nom).Roi(rois2take(1)).LineSpec]); @@ -802,16 +840,17 @@ function update(no) for loop=2:size(gui.netflow,2) h = plot(gui.handles.plotaxes,t*1000,gui.posflow(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end for loop=1:size(gui.negflow,2) h = plot(gui.handles.plotaxes,t*1000,gui.negflow(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2,'linestyle',':'); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); - title(gui.handles.plotaxes,dprintf('Positive (-) / Negative (:) flow. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Flow [ml/s]')); + title(gui.handles.plotaxes,dprintf('Positive (-) / Negative (:) flow. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Flow [ml/s]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case 3 %'Velocity' %--- Plot velocity @@ -821,7 +860,7 @@ function update(no) for loop=2:size(gui.velmean,2) h = plot(gui.handles.plotaxes,t*1000,gui.velmean(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end %--- Plot std bars plot(... @@ -865,12 +904,13 @@ function update(no) [t'*1000-dt t'*1000+dt]',... [gui.velmean(:,loop)+gui.velstd(:,loop) gui.velmean(:,loop)+gui.velstd(:,loop)]',... SET(nom).Roi(1).LineSpec); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); - title(gui.handles.plotaxes,dprintf('Mean velocity. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Mean velocity [cm/s]')); + title(gui.handles.plotaxes,dprintf('Mean velocity. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Mean velocity [cm/s]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case 4 %'Max Velocity' %--- Plot max @@ -880,12 +920,13 @@ function update(no) for loop=2:size(gui.area,2) h = plot(gui.handles.plotaxes,t*1000,gui.velmax(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); - title(gui.handles.plotaxes,dprintf('Max velocity. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Max velocity [cm/s]')); + title(gui.handles.plotaxes,dprintf('Max velocity. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Max velocity [cm/s]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case 5 %'Min Velocity' %--- Plot min @@ -895,12 +936,13 @@ function update(no) for loop=2:size(gui.area,2) h = plot(gui.handles.plotaxes,t*1000,gui.velmin(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); - title(gui.handles.plotaxes,dprintf('Min velocity. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Min velocity [cm/s]')); + title(gui.handles.plotaxes,dprintf('Min velocity. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Min velocity [cm/s]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case 6 %'Signed Kinetic Energy' %--- Plot KE @@ -910,12 +952,13 @@ function update(no) for loop=2:size(gui.area,2) h = plot(gui.handles.plotaxes,t*1000,gui.kenergy(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); - title(gui.handles.plotaxes,dprintf('Signed Kinetic Energy. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Signed Kinetic Energy [Nm/s]')); + title(gui.handles.plotaxes,dprintf('Signed Kinetic Energy. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Signed Kinetic Energy [Nm/s]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case 7 %'Area' %--- Plot area @@ -925,13 +968,14 @@ function update(no) for loop=2:size(gui.area,2) h = plot(gui.handles.plotaxes,t*1000,gui.area(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); set(gui.handles.plotaxes,'ylim',[0 1.2*max(max(gui.area))]); - title(gui.handles.plotaxes,dprintf('Area. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Area [cm^2]')); + title(gui.handles.plotaxes,dprintf('Area. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Area [cm^2]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case 8 %'Diameter' %--- Plot diameter @@ -941,13 +985,14 @@ function update(no) for loop=2:size(gui.diameter,2) h = plot(gui.handles.plotaxes,t*1000,gui.diameter(:,loop),[d SET(nom).Roi(rois2take(loop)).LineSpec]); set(h,'linewidth',2); - end; + end + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); hold(gui.handles.plotaxes,'off'); set(gui.handles.plotaxes,'xlim',[0 (SET(nom).TSize-1)*1000*SET(nom).TIncr]); set(gui.handles.plotaxes,'ylim',[0 1.2*max(max(gui.diameter))]); - title(gui.handles.plotaxes,dprintf('Diameter. %s',gui.phasecorrstring),'FontSize',12); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,translation.dictionary('Diameter [mm]')); + title(gui.handles.plotaxes,dprintf('Diameter. %s',gui.phasecorrstring),'FontSize',12,'Color',DATA.GUISettings.ForegroundColor); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,dprintf('Diameter [mm]'),'Color',DATA.GUISettings.ForegroundColor); grid(gui.handles.plotaxes,'on'); case {9,10,11} %{'3D plot','3D plot one frame','Pixel Export'} %--- 3D plot @@ -979,7 +1024,7 @@ function update(no) if ~isempty(pos) left = min(left,pos(1)); right = max(right,pos(end)); - end; + end %Find up/down extent temp = sum(mask(:,:,tloop-timeframes(1)+1),2); @@ -987,9 +1032,9 @@ function update(no) if ~isempty(pos) up = min(up,pos(1)); down = max(down,pos(end)); - end; + end end - end; + end %Add extra space around left = max(left-1,1); @@ -1009,15 +1054,17 @@ function update(no) if v == 10 %strcmp(s{v},'3D plot one frame') %3D plot option flow('flow3dmovie_Callback',mask,double(scaling),nop,up,down,left,right); - end; + end if v == 9 %strcmp(s{v},'3D plot') %Plot all 3d plots in one figure. - figure(18+rloop); - set(18+rloop,... + fig = figure(18+rloop); + setupicon(fig); + set(fig,... 'Name',dprintf('3D velocity profile %s',SET(nom).Roi(rois2take(rloop)).Name),... 'Numbertitle','off'); clf; + hold on; for tloop=1:length(timeframes) @@ -1037,20 +1084,20 @@ function update(no) temp = SET(nom).Roi(rois2take(rloop)).Sign*mask(:,:,tloop).*... (SET(nop).IM(:,:,timeframes(tloop),SET(nom).Roi(rois2take(rloop)).Z)-0.5-... SET(nop).Flow.PhaseCorr(:,:,1,SET(nom).Roi(rois2take(rloop)).Z))*2*SET(SET(nom).Flow.PhaseNo).VENC; - end; - end; + end + end temp = temp(up:down,left:right); temp = double(temp); dx = mod(tloop-1,xs); dy = ceil(tloop/xs)-1; h = surf(y+dy*y(end),x+dx*x(end),0.25*temp*scaling); %#ok - end; + end hold off; axis off image vis3d; rotate3d on; - cameratoolbar(18+rloop); - end; + cameratoolbar(fig); + end if v == 11 %strcmp(s{v},'Pixel Export') %Export all pixeldata. @@ -1133,20 +1180,20 @@ function update(no) temp = SET(nom).Roi(rois2take(rloop)).Sign*mask(:,:,tloop).*... (SET(nop).IM(:,:,timeframes(tloop),SET(nom).Roi(rois2take(rloop)).Z)-0.5-... SET(nop).Flow.PhaseCorr(:,:,1,SET(nom).Roi(rois2take(rloop)).Z))*2*SET(SET(nom).Flow.PhaseNo).VENC; - end; - end; + end + end temp = temp(up:down,left:right); temp = double(temp); outdata(rowoffset+(tloop-1)*(ysize+2)+(1:ysize),1:xsize) = num2cell(temp); outdata{rowoffset+(tloop-1)*(ysize+2),1} = 'Time [ms]:'; outdata{rowoffset+(tloop-1)*(ysize+2),2} = (tloop-1)*SET(nom).TIncr*1000; - end; + end segment('cell2clipboard',outdata); - end; + end - end; -end; %Case clause + end +end %Case clause %Add the red bars, legend, not 3D xstart = SET(nom).TIncr*(SET(nom).StartAnalysis-1)*1000; @@ -1158,6 +1205,12 @@ function update(no) set(h,'linewidth',2,'ButtonDownFcn','reportflow(''flowbar_Buttondown'',''startbar'')'); h = plot(gui.handles.plotaxes,[xend xend],ylim,'g-'); set(h,'linewidth',2,'ButtonDownFcn','reportflow(''flowbar_Buttondown'',''endbar'')'); + %JB: Reverting change 8241 +% % % % y = median(gui.netflow(:)); +% % % % if isequal(mygetlistbox(gui.handles.parameterlistbox),1) +% % % % h = plot(gui.handles.plotaxes,1000*[t(1) t(end)],[y y],'r:'); +% % % % set(h,'linewidth',2,'ButtonDownFcn','reportflow(''baselinebar_Buttondown'')'); +% % % % end hold(gui.handles.plotaxes,'off'); %--- Legend @@ -1167,10 +1220,13 @@ function update(no) temp{loop} = [SET(nom).Roi(rois2take(loop)).Name ' (Sign switched)']; else temp{loop} = SET(nom).Roi(rois2take(loop)).Name; - end; - end; + end + end legend(gui.handles.plotaxes,temp{:}); -end; +end + +gui.handles.plotaxes.GridColor = 'k'; +set(gui.handles.plotaxes,'Color',[0.94 0.94 0.94]); %-------------- function export %#ok @@ -1208,7 +1264,7 @@ function update(no) outdata{1+loop, 8} = gui.velmin(loop); outdata{1+loop, 9} = gui.velmax(loop); outdata{1+loop, 10} = gui.area(loop); - end; + end else %For time resolved Phase Contrast Images if gui.resamped @@ -1223,7 +1279,7 @@ function update(no) outdata{2,1} = 'Time[ms]'; for loop=1:numrois outdata{1,2+(loop-1)*9} = SET(nom).Roi(rois2take(loop)).Name; -end; +end %--- Second header for loop=1:numrois @@ -1236,7 +1292,7 @@ function update(no) outdata{2,8+(loop-1)*9} = 'Total flow [ml/s]'; outdata{2,9+(loop-1)*9} = 'Positive flow [ml/s]'; outdata{2,10+(loop-1)*9} = 'Negative flow [ml/s]'; -end; +end %--- Data for tloop=timeframes @@ -1252,8 +1308,8 @@ function update(no) outdata{row,8+(loop-1)*9} = gui.netflow(tloop,loop); outdata{row,9+(loop-1)*9} = gui.posflow(tloop,loop); outdata{row,10+(loop-1)*9} = gui.negflow(tloop,loop); - end; -end; + end +end %--- Integral flow row = row+2; @@ -1285,7 +1341,7 @@ function update(no) %(net ml)/1000 => L %time ms)/1000*60 => [min] row = row+1; -end; +end end segment('cell2clipboard',outdata); @@ -1304,32 +1360,33 @@ function flowbar_Buttondown(type) %#ok function flowbar_Buttonup(type) %#ok %------------------------------ %Button up function for flow bar in flow report GUI. -global SET NO - +global SET DATA NO +gui = DATA.GUI.Flow; +nom = gui.nom; set(gcf,'WindowButtonMotionFcn',''); set(gcf,'WindowButtonUpFcn',''); %Get Convert to timeframe x = get(SET(NO).Flow.temphandle,'xdata'); x = x(1); -x = round(1+x/(1000*SET(NO).TIncr)); -x = max(min(x,SET(NO).TSize),1); +x = round(1+x/(1000*SET(nom).TIncr)); +x = max(min(x,SET(nom).TSize),1); switch type case 'startbar' - SET(NO).StartAnalysis = x; + SET(nom).StartAnalysis = x; case 'endbar' - SET(NO).EndAnalysis = x; -end; + SET(nom).EndAnalysis = x; +end -if SET(NO).StartAnalysis>SET(NO).EndAnalysis - temp = SET(NO).StartAnalysis; - SET(NO).StartAnalysis=SET(NO).EndAnalysis; - SET(NO).EndAnalysis=temp; -end; +if SET(nom).StartAnalysis > SET(nom).EndAnalysis + temp = SET(nom).StartAnalysis; + SET(nom).StartAnalysis = SET(nom).EndAnalysis; + SET(nom).EndAnalysis = temp; +end %Recalculate to get correct flow -recalculate(NO); +recalculate(nom); %---------------------- function flowbar_Motion %#ok @@ -1349,6 +1406,59 @@ function flowbar_Buttonup(type) %#ok %Update display set(SET(NO).Flow.temphandle,'xdata',[x x]); +%------------------------------- +function baselinebar_Buttondown %#ok +%------------------------------- +%Button down function for flow bar in flow report GUI. +global SET NO + +SET(NO).Flow.temphandle = gcbo; +set(gcf,'WindowButtonMotionFcn','reportflow(''baselinebar_Motion'')'); +set(gcf,'WindowButtonUpFcn','reportflow(''baselinebar_Buttonup'')'); + +%-------------------------- +function baselinebar_Motion %#ok +%-------------------------- +%Motion function for flowbar. +global SET NO + +[~,y] = mygetcurrentpoint(gca); + +%Update display +set(SET(NO).Flow.temphandle,'ydata',[y y]); + +%---------------------------- +function baselinebar_Buttonup %#ok +%---------------------------- +%Button up function for flow bar in flow report GUI. + +global DATA SET NO + +set(gcf,'WindowButtonMotionFcn',''); +set(gcf,'WindowButtonUpFcn',''); + +gui = DATA.GUI.Flow; + +phno = SET(NO).Flow.PhaseNo; + +%Compute median and difference +m = median(gui.netflow(:)); +y = get(SET(NO).Flow.temphandle,'ydata'); +y = y(1); +d = m-y; %ml/s +area = sum(mean(gui.area)); %sum of the mean area +dvel = d/area; +dvel = dvel/SET(phno).VENC/2; +%Check if no phase correction computed +if isempty(SET(phno).Flow.PhaseCorr) + SET(phno).Flow.PhaseCorr = zeros(SET(phno).XSize,SET(phno).YSize,SET(phno).ZSize); +end + +SET(phno).Flow.PhaseCorr = SET(phno).Flow.PhaseCorr+dvel; + +%Recalculate to get correct flow +recalculate(NO); + %--------------------------- function datacursor_Callback %#ok %--------------------------- @@ -1364,14 +1474,14 @@ function flowbar_Buttonup(type) %#ok function switchsign_Callback %#ok %--------------------------- %switch flow sign of current roi and recalucate and update -global NO DATA +global NO DATA SET gui = DATA.GUI.Flow; roi('roiswitchsign_Callback'); -if DATA.TInt <= 0 %For non-time resolced Phase Contrast Images +if SET(NO).TSize <= 1 %For non-time resolced Phase Contrast Images %switch all the signs where it has impact gui.velmean = - gui.velmean; tmpmax = -gui.velmax; @@ -1406,4 +1516,5 @@ function flowbar_Buttonup(type) %#ok %----------------------------- %open the eddy current compensation gui and recalculate and update -floweddycurrent('initsmall'); \ No newline at end of file +floweddycurrent('initsmall'); +update; \ No newline at end of file diff --git a/source/reportradvel.m b/source/reportradvel.m index 60ae0cb..f686675 100644 --- a/source/reportradvel.m +++ b/source/reportradvel.m @@ -11,7 +11,7 @@ if isempty(SET(NO).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end tempnos=NO; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -27,17 +27,13 @@ if nslices<1 myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end -fig = openfig('reportradvel.fig','reuse'); -myadjust(fig,DATA.GUI.Segment); -blockfig(fig); -translation.translatealllabels(fig); -% Use system color scheme for figure: -set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); +fig = mygui('reportradvel.fig'); % Generate a structure of handles to pass to callbacks, and store it. -handles = guihandles(fig); +handles = fig.handles; +handles.fig = handles.figure1; %Calculate over sectors [meanradvel,meanx,meany,sectors] = calcfunctions('findmeaninsector',... @@ -64,21 +60,17 @@ axis off; hold on -h = plot(... - SET(NO).EndoY(:,tf,cs),... - SET(NO).EndoX(:,tf,cs),... - 'r-'); +h = line('XData',SET(NO).EndoY(:,tf,cs),'YData',SET(NO).EndoX(:,tf,cs),'Color','r','LineStyle','-'); set(h,'linewidth',3); for loop=1:6 - plot(... - [meany(tf,cs) SET(NO).EndoY(sectors(loop,1,tf),tf,cs)],... - [meanx(tf,cs) SET(NO).EndoX(sectors(loop,1,tf),tf,cs)],... - 'r-'); + line('XData',[meany(tf,cs) SET(NO).EndoY(sectors(loop,1,tf),tf,cs)],... + 'YData',[meanx(tf,cs) SET(NO).EndoX(sectors(loop,1,tf),tf,cs)],... + 'Color','r','LineStyle','-'); text(... 0.5*(SET(NO).EndoY(sectors(loop,1,tf),tf,cs)+SET(NO).EndoY(sectors(loop+1,1,tf),tf,cs)),... 0.5*(SET(NO).EndoX(sectors(loop,1,tf),tf,cs)+SET(NO).EndoX(sectors(loop+1,1,tf),tf,cs)),... sprintf('%d',loop)); -end; +end hold off; axis off; axis image; @@ -105,7 +97,7 @@ function helpimageposneg(im,sector,konst) %--------------------------------------- %Helper function to display image. -global SET NO +global SET NO DATA im = im(sector,:,:); im = squeeze(im); @@ -113,5 +105,6 @@ function helpimageposneg(im,sector,konst) h = image(32+konst*im); set(h,'xdata',SET(NO).TIncr*[0.5 SET(NO).TSize+0.5]); set(gca,'yticklabel','','xlim',[0 (SET(NO).TSize-1)*SET(NO).TIncr]); -xlabel(translation.dictionary('Time')); -title(dprintf(translation.dictionary('Sector %d'),sector)); +set(gca,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); +xlabel(dprintf('Time'),'Color',DATA.GUISettings.ForegroundColor); +title(dprintf('Sector %d',sector),'Color',DATA.GUISettings.ForegroundColor); diff --git a/source/reportroi.m b/source/reportroi.m index 5fc01d0..aac7785 100644 --- a/source/reportroi.m +++ b/source/reportroi.m @@ -16,21 +16,21 @@ if SET(NO).RoiN<1 myfailed('No ROIs available. Use blue pen to draw ROIs.',DATA.GUI.Segment); return; -end; +end -tempnos=NO; -imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants +tempnos = NO; +imissingle = classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants if not(imissingle) return; end if isempty(SET(NO).EndAnalysis) SET(NO).EndAnalysis = SET(NO).TSize; -end; +end if isempty(SET(NO).StartAnalysis) SET(NO).StartAnalysis = 1; -end; +end %if (SET(NO).EndAnalysis-SET(NO).StartAnalysis)<1 % myfailed('No timespan, adjust Start/End analysis time (under stress menu or drag red bar).',DATA.GUI.Segment); @@ -38,17 +38,20 @@ % %end; -%Open gui -%check if open +%--- Open gui +%Check if open if isopengui('roi.fig') close_Callback; end +%Open gui = mygui('roi.fig'); DATA.GUI.ROI = gui; if ~isrectilinear(SET(NO).TimeVector) gui.rectilinear = false; -end; +else + gui.rectilinear = true; +end % mywarning(['Non uniform time steps detected. Smoothing and display of '... % 'min/max slope disabled.']); @@ -56,12 +59,12 @@ % gui.handles.showslopescheckbox],'enable','off'); %end -%Ask for what ROI's to include +%--- Ask for what ROI's to include [gui.rois,~,gui.normalized] = roi('roiselector','',... get(gui.handles.thissliceonlycheckbox,'value'),... '',get(gui.handles.normalizedcheckbox,'value')); -%Initalize variables +%--- Initalize variables gui.no = NO; gui.t = SET(NO).TimeVector; gui.t = gui.t*1000; %ms @@ -71,12 +74,21 @@ gui.roisize = gui.roiint; gui.roimin = gui.roiint; gui.roimax = gui.roiint; +%Smooth feature gui.sigma = mygetvalue(gui.handles.smoothslider); -gui.offset = 0; +set(gui.handles.sigmaedit,'string',sprintf('%0.5g',gui.sigma)); +%Detrend feature gui.detrendstartms = 0; gui.detrendendvalue = 0; -set(gui.handles.sigmaedit,'string',sprintf('%0.5g',gui.sigma)); +%Offset feature +gui.offset = 0; +gui.offsetrange = 1; +gui.normalizedold = 1; %GUI launches with non-norm. values +gui.intoffset = SET(gui.no).IntensityOffset; %used to rescale offset +gui.intscaling = SET(gui.no).IntensityScaling; %used to rescale offset +gui.venc = SET(gui.no).VENC; %used to rescale offset +%--- Extract, process and plot data recalc; %do plot % datacursormode(gui.fig) @@ -95,7 +107,7 @@ n = str2double(s); if not(isnan(n)) gui.sigma = n; -end; +end gui.sigma = min(max(gui.sigma,get(gui.handles.smoothslider,'min')),get(gui.handles.smoothslider,'max')); set(gui.handles.sigmaedit,'string',sprintf('%0.5g',gui.sigma)); set(gui.handles.smoothslider,'value',gui.sigma); @@ -113,30 +125,47 @@ %------------------ function offsetedit %#ok %------------------ +%Get offset value from user defined value in editbox global DATA gui = DATA.GUI.ROI; +%--- Get value temp = mygetedit(gui.handles.offsetedit); -[num,ok] = str2num(temp); %#ok -if ok +num = str2double(temp); + +if ~isnan(num) + %--- Limit user's input value to offset range and store value + if num > gui.offsetrange + gui.offset = gui.offsetrange; + elseif num < -gui.offsetrange + gui.offset = -gui.offsetrange; + else gui.offset = num; - set(gui.handles.offsetslider,'value',num); + end + %--- Pass offset value to offset slider + set(gui.handles.offsetslider,'value',gui.offset); else myfailed('Could not interpret number.',DATA.GUI.Segment); return; -end; +end + +%--- Update plot doplot; %-------------------- function offsetslider %#ok %-------------------- -%User adjusted offsetslider - +%Get offset value from user defined value in slider global DATA gui = DATA.GUI.ROI; +%--- Get and store value gui.offset = mygetvalue(gui.handles.offsetslider); + +%--- Pass offset value to offset editbox set(gui.handles.offsetedit,'string',sprintf('%0.5g',gui.offset)); + +%--- Update plot doplot; %--------------------------- @@ -151,9 +180,9 @@ s.DetrendEndValue = gui.detrendendvalue; [s,ok] = inputstruct(s); if ~ok - myfailed('Aborted.'); +% myfailed('Aborted.'); return; -end; +end gui.detrendstartms = s.DetrendStart_ms; gui.detrendendvalue = s.DetrendEndValue; @@ -245,13 +274,13 @@ function roibar_Buttonup(type) %#ok SET(NO).StartAnalysis = x; case 'endbar' SET(NO).EndAnalysis = x; -end; +end if SET(NO).StartAnalysis>SET(NO).EndAnalysis temp = SET(NO).StartAnalysis; SET(NO).StartAnalysis=SET(NO).EndAnalysis; SET(NO).EndAnalysis=temp; -end; +end %Do graphical update doplot; @@ -288,9 +317,9 @@ function roibar_Buttonup(type) %#ok x = linspace(-60,60,121); f = exp(-x.^2/gui.sigma.^2); figure(22); -plot(x,f); -xlabel('Timeframes'); -title('Smoothing applicability.'); +line('XData',x,'YData',f); +xlabel(dprintf('Timeframes')); +title(dprintf('Smoothing applicability.')); %-------------- function recalc @@ -302,6 +331,13 @@ function roibar_Buttonup(type) %#ok [gui.rois,~,gui.normalized] = roi('roiselector','',... get(gui.handles.thissliceonlycheckbox,'value'),... '',get(gui.handles.normalizedcheckbox,'value')); +%Check if offset needs to be recalculated +if gui.normalizedold == gui.normalized + recalcoffsetflag = false; +else + recalcoffsetflag = true; +end +gui.normalizedold = gui.normalized; %--- Extract data h = mywaitbarstart(length(gui.rois),'Please wait, calculating data',[],DATA.GUI.Segment); @@ -313,7 +349,7 @@ function roibar_Buttonup(type) %#ok temp = SET(gui.no).IM(:,:,tloop,z); else temp = calcfunctions('calctruedata',SET(gui.no).IM(:,:,tloop,z),gui.no); - end; + end roimask = segment('createmask',... [SET(gui.no).XSize SET(gui.no).YSize],... SET(gui.no).Roi(gui.rois(rloop)).Y(:,tloop),... @@ -324,16 +360,23 @@ function roibar_Buttonup(type) %#ok gui.roimax(tloop,rloop) = max(temp(ind)); gui.roiint(tloop,rloop) = mean(temp(ind)); gui.roistd(tloop,rloop) = std(temp(ind)); - end; + end gui.roisize(tloop,rloop) = (1/100)*polyarea(... SET(gui.no).ResolutionY*SET(gui.no).Roi(gui.rois(rloop)).Y(:,tloop),... SET(gui.no).ResolutionX*SET(gui.no).Roi(gui.rois(rloop)).X(:,tloop)); gui.roisizepix(tloop,rloop) = sum(roimask(:))*SET(gui.no).ResolutionX*SET(gui.no).ResolutionY/100; - end; - end; + end + end h = mywaitbarupdate(h); -end; +end mywaitbarclose(h); + +%--- Compute new offset +if recalcoffsetflag + recalcoffset; +end + +%--- Process and plot data doplot; set(gui.fig,'Pointer','Arrow'); @@ -347,56 +390,65 @@ function roibar_Buttonup(type) %#ok switch mygetlistbox(gui.handles.parameterlistbox) case 1 gui.outdata = gui.roiint; - gui.outname = translation.dictionary('Mean Intensity'); + gui.outname = dprintf('Mean Intensity'); if (SET(gui.no).TSize==1) %sbt20160516, mod EH - auc = gui.outdata;%sbt20160516 + auc = gui.outdata;%sbt20160516 elseif (numel(gui.t)>1)%sbt20160516 for lloop=1:length(gui.rois) auc(lloop) = trapz(gui.t/1000,gui.outdata(:,lloop)); end else%sbt20160516 - myfailed('Error: unknown number of timeframes found.')%sbt20160516 - auc = 0;%sbt20160516 + myfailed('Error: unknown number of timeframes found.')%sbt20160516 + auc = 0;%sbt20160516 end%sbt20160516 + set(gui.handles.offsetslider,'Enable','on'); + set(gui.handles.offsetedit,'Enable','on'); + set(gui.handles.offsetedit,'string',sprintf('%0.5g',gui.offset)); set(gui.handles.auctext,'Visible','on'); - aucstring = sprintf('Area under curve:\n'); + aucstring = dprintf('Area under curve:\n'); for lloop=1:length(gui.rois) - aucstring = [aucstring dprintf('%s: %0.2f\n',SET(gui.no).Roi(gui.rois(lloop)).Name,auc(lloop))]; + aucstring = [aucstring sprintf('%s: %0.2f\n',SET(gui.no).Roi(gui.rois(lloop)).Name,auc(lloop))]; end set(gui.handles.auctext,'String',aucstring); case 2 gui.outdata = gui.roistd; - gui.outname = translation.dictionary('Standard deviation'); + gui.outname = dprintf('Standard deviation'); set(gui.handles.auctext,'Visible','off'); + disableoffset; case 3 gui.outdata = gui.roisize; - gui.outname = translation.dictionary('Area [cm^2]'); + gui.outname = dprintf('Area [cm^2]'); set(gui.handles.auctext,'Visible','off'); + disableoffset; case 4 gui.outdata = gui.roisizepix; - gui.outname = translation.dictionary('Area based on pixels [cm^2] '); + gui.outname = dprintf('Area based on pixels [cm^2] '); set(gui.handles.auctext,'Visible','off'); + disableoffset; case 5 gui.outdata = gui.roimax; - gui.outname = translation.dictionary('Maximum intensity'); + gui.outname = dprintf('Maximum intensity'); set(gui.handles.auctext,'Visible','off'); + disableoffset; case 6 gui.outdata = gui.roimin; - gui.outname = translation.dictionary('Minimum intensity'); + gui.outname = dprintf('Minimum intensity'); set(gui.handles.auctext,'Visible','off'); + disableoffset; otherwise myfailed('Not yet implemented.',DATA.GUI.Segment); gui.outdata = []; gui.outname = ''; -end; +end +%--- Process data %Add offset gui.outdata = gui.outdata+gui.offset; %Crop data if get(gui.handles.cropzerocheckbox,'value') gui.outdata(gui.outdata<0) = 0; -end; +end %Detrend data if get(gui.handles.detrendcheckbox,'value') @@ -409,7 +461,7 @@ function roibar_Buttonup(type) %#ok detrend = detrend(:); %reshape detrend = repmat(detrend,[1 size(gui.outdata,2)]); %reshape gui.outdata = gui.outdata-detrend; -end; +end %--- Do smoothing if dosmooth @@ -432,19 +484,19 @@ function roibar_Buttonup(type) %#ok else %Normalized averaging, rectilinear code signalfiltered = conv2(signal,f','same')./(eps+conv2(ones(size(signal)),f','same')); - end; + end %Store gui.smoothoutdata(:,rloop) = signalfiltered; - end; + end else gui.smoothoutdata = gui.outdata; gui.t = SET(gui.no).TimeVector*1000; -end; +end -%--- Plot it +%--- Plot data if SET(gui.no).TSize>1 @@ -478,7 +530,8 @@ function roibar_Buttonup(type) %#ok else plot(gui.handles.plotaxes,gui.t,gui.outdata(:,rloop),sprintf('%so',SET(gui.no).Roi(gui.rois(rloop)).LineSpec(1))); end - end; + end + %--- Calc min/max/slope %Loop over rois @@ -498,7 +551,7 @@ function roibar_Buttonup(type) %#ok tempd(SET(gui.no).EndAnalysis+1:end) = NaN; [gui.minvd(rloop),gui.minindd(rloop)] = min(tempd); [gui.maxvd(rloop),gui.maxindd(rloop)] = max(tempd); - end; + end %FWHM gui.fwhm(rloop) = 0.5*(gui.maxv(rloop)+gui.minv(rloop)); @@ -512,7 +565,7 @@ function roibar_Buttonup(type) %#ok else gui.fwhmstart(rloop) = pos(1); gui.fwhmend(rloop) = pos(end); - end; + end %Centerofgravity temp = gui.smoothoutdata(SET(gui.no).StartAnalysis:SET(gui.no).EndAnalysis,rloop); @@ -523,7 +576,7 @@ function roibar_Buttonup(type) %#ok gui.centergravity(rloop) = temp_nom/temp_den; else gui.centergravity(rloop) = NaN; - end; + end %Plot max/min if mygetvalue(gui.handles.showminmaxcheckbox) @@ -531,28 +584,31 @@ function roibar_Buttonup(type) %#ok plot(gui.handles.plotaxes,gui.t(gui.maxind(rloop)),gui.maxv(rloop),'k*'); plot(gui.handles.plotaxes,[gui.t(1) gui.t(end)],[gui.minv(rloop) gui.minv(rloop)],'k:'); plot(gui.handles.plotaxes,[gui.t(1) gui.t(end)],[gui.maxv(rloop) gui.maxv(rloop)],'k:'); - end; + end %Plot min/max slopes if mygetvalue(gui.handles.showslopescheckbox) temp = gui.smoothoutdata(:,rloop); - plot(gui.handles.plotaxes,gui.t(gui.maxindd(rloop)),temp(gui.maxindd(rloop)),'ko'); - plot(gui.handles.plotaxes,gui.t(gui.minindd(rloop)),temp(gui.minindd(rloop)),'ko'); - - ylim = get(gui.handles.plotaxes,'ylim'); - - deltat = gui.t(end)*0.03; - left = temp(gui.minindd(rloop))-gui.minvd(rloop)*deltat; - right = temp(gui.minindd(rloop))+gui.minvd(rloop)*deltat; - plot(gui.handles.plotaxes,gui.t(gui.minindd(rloop))+[-deltat deltat],[left right],'k-'); - plot(gui.handles.plotaxes,[gui.t(gui.minindd(rloop)) gui.t(gui.minindd(rloop))],ylim,'k:'); - - deltat = gui.t(end)*0.03; - left = temp(gui.maxindd(rloop))-gui.maxvd(rloop)*deltat; - right = temp(gui.maxindd(rloop))+gui.maxvd(rloop)*deltat; - plot(gui.handles.plotaxes,gui.t(gui.maxindd(rloop))+[-deltat deltat],[left right],'k-'); - plot(gui.handles.plotaxes,[gui.t(gui.maxindd(rloop)) gui.t(gui.maxindd(rloop))],ylim,'k:'); - end; + if any(gui.maxindd == 0) + myfailed('Need to smooth data first.',DATA.GUI.ROI); + set(gui.handles.showslopescheckbox,'Value',0) + else + plot(gui.handles.plotaxes,gui.t(gui.maxindd(rloop)),temp(gui.maxindd(rloop)),'ko'); + plot(gui.handles.plotaxes,gui.t(gui.minindd(rloop)),temp(gui.minindd(rloop)),'ko'); + ylim = get(gui.handles.plotaxes,'ylim'); + + deltat = gui.t(end)*0.03; + left = temp(gui.minindd(rloop))-gui.minvd(rloop)*deltat; + right = temp(gui.minindd(rloop))+gui.minvd(rloop)*deltat; + plot(gui.handles.plotaxes,gui.t(gui.minindd(rloop))+[-deltat deltat],[left right],'k-'); + plot(gui.handles.plotaxes,[gui.t(gui.minindd(rloop)) gui.t(gui.minindd(rloop))],ylim,'k:'); + deltat = gui.t(end)*0.03; + left = temp(gui.maxindd(rloop))-gui.maxvd(rloop)*deltat; + right = temp(gui.maxindd(rloop))+gui.maxvd(rloop)*deltat; + plot(gui.handles.plotaxes,gui.t(gui.maxindd(rloop))+[-deltat deltat],[left right],'k-'); + plot(gui.handles.plotaxes,[gui.t(gui.maxindd(rloop)) gui.t(gui.maxindd(rloop))],ylim,'k:'); + end + end %Plot FWHM if mygetvalue(gui.handles.showfwhmcheckbox)&&~isnan(gui.fwhmstart(rloop)) @@ -560,41 +616,42 @@ function roibar_Buttonup(type) %#ok plot(gui.handles.plotaxes,[gui.t(1) gui.t(end)],[gui.fwhm(rloop) gui.fwhm(rloop)],'k:'); plot(gui.handles.plotaxes,[gui.t(gui.fwhmstart(rloop)) gui.t(gui.fwhmstart(rloop))],ylim,'k:'); plot(gui.handles.plotaxes,[gui.t(gui.fwhmend(rloop)) gui.t(gui.fwhmend(rloop))],ylim,'k:'); - end; + end %Plot CenterGravity if mygetvalue(gui.handles.showcentergravitycheckbox) ylim = get(gui.handles.plotaxes,'ylim'); pos = (gui.centergravity(rloop)-1)*SET(gui.no).TIncr*1000; plot(gui.handles.plotaxes,[pos pos],ylim,'k:'); - end; + end - end; %rloop + end %rloop %Plot smoothed curves if dosmooth for rloop=1:size(gui.outdata,2) h = plot(gui.handles.plotaxes,gui.t,gui.smoothoutdata(:,rloop),'k:'); %SET(gui.no).RoiLineSpec{gui.rois(rloop)}); set(h,'linewidth',2); - end; - end; + end + end %Add red bars - ylim = get(gui.handles.plotaxes,'ylim'); + ylim = get(gui.handles.plotaxes,'ylim'); h = plot([gui.t(SET(gui.no).StartAnalysis) gui.t(SET(gui.no).StartAnalysis)],ylim,'r-'); set(h,'linewidth',2,'ButtonDownFcn','reportroi(''roibar_Buttondown'',''startbar'')'); - h = plot([gui.t(SET(gui.no).EndAnalysis) gui.t(SET(gui.no).EndAnalysis)],ylim,'r-'); + h = plot([gui.t(SET(gui.no).EndAnalysis) gui.t(SET(gui.no).EndAnalysis)],ylim,'r-'); set(h,'linewidth',2,'ButtonDownFcn','reportroi(''roibar_Buttondown'',''endbar'')'); hold(gui.handles.plotaxes,'off'); %Add legend and labels + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); legendstring=cell(1,length(gui.rois)); for lloop=1:length(gui.rois) legendstring{lloop}=SET(gui.no).Roi(gui.rois(lloop)).Name; end legend(gui.handles.plotaxes,legendstring); - xlabel(gui.handles.plotaxes,translation.dictionary('Time [ms]')); - ylabel(gui.handles.plotaxes,gui.outname); + xlabel(gui.handles.plotaxes,dprintf('Time [ms]'),'Color',DATA.GUISettings.ForegroundColor); + ylabel(gui.handles.plotaxes,gui.outname,'Color',DATA.GUISettings.ForegroundColor); else %not time resolved @@ -605,8 +662,55 @@ function roibar_Buttonup(type) %#ok bar(gui.handles.plotaxes,gui.outdata(gui.rois)'); set(gui.handles.plotaxes,'xtick',1:1:length(legendstring)); set(gui.handles.plotaxes,'xticklabel',legendstring); + set(gui.handles.plotaxes,'XColor',DATA.GUISettings.ForegroundColor,'YColor',DATA.GUISettings.ForegroundColor); + +end + +%-------------- +function disableoffset +%-------------- +%Disable offset slider and offset edit box in ROI analyser GUI. +%Used when parameter to plot is not Mean Intensity. +global DATA +gui = DATA.GUI.ROI; + +set(gui.handles.offsetslider,'Enable','off'); +set(gui.handles.offsetedit,'Enable','off'); +set(gui.handles.offsetedit,'string',0); -end; +%-------------- +function recalcoffset +%-------------- +%Used in case of recalculation, if the user switches between normalized and +%non-normalized data. +%Set new offset range and compute new offset value according to whether the +%data used in the plot are normalized or not. True offset is computed using +%IntensityScaling and IntensityOffset stored in SET structure. +global DATA +gui = DATA.GUI.ROI; + +if gui.normalized + %Normalized offset range + gui.offsetrange = 1; + %Normalized offset value + gui.offset = (gui.offset - gui.intoffset) / gui.intscaling; +else + %True offset range + gui.offsetrange = gui.intscaling + gui.intoffset; + %True offset value + if ~isempty(gui.intscaling) + gui.offset = gui.offset * gui.offsetrange; + elseif ~isempty(gui.venc) && gui.venc ~= 0 + gui.offset = (gui.offset-0.5) * 2*gui.venc; + else + gui.offset = gui.offset; + end +end + +%Set new offset range and new offset value for offset slider +set(gui.handles.offsetslider,'Min',-gui.offsetrange); +set(gui.handles.offsetslider,'Max',gui.offsetrange); +set(gui.handles.offsetslider,'value',gui.offset); %-------------- function export %#ok @@ -620,21 +724,21 @@ function roibar_Buttonup(type) %#ok if dosmooth c{1,2} = 'Smoothing sigma [timeframes]'; c{1,3} = gui.sigma; -end; +end c{4,1} = 'Time[ms]'; for rloop=1:length(gui.rois) if dosmooth c{4,(rloop-1)*7+2} = sprintf('Smoothed:%s',gui.outname); else c{4,(rloop-1)*7+2} = sprintf('%s',gui.outname); - end; + end c{4,(rloop-1)*7+3} = 'Intensity'; c{4,(rloop-1)*7+4} = 'SD'; c{4,(rloop-1)*7+5} = 'Size[cm2]'; c{4,(rloop-1)*7+6} = 'Pixsize[cm2]'; c{4,(rloop-1)*7+7} = 'Max'; c{4,(rloop-1)*7+8} = 'Min'; -end; +end for rloop=1:length(gui.rois) roiname{rloop} = SET(gui.no).Roi(gui.rois(rloop)).Name; @@ -660,8 +764,8 @@ function roibar_Buttonup(type) %#ok c{tloop+4,(rloop-1)*7+6} = gui.roisizepix(tloop,exportindex(rloop)); c{tloop+4,(rloop-1)*7+7} = gui.roimax(tloop,exportindex(rloop)); c{tloop+4,(rloop-1)*7+8} = gui.roimin(tloop,exportindex(rloop)); - end; -end; + end +end segment('cell2clipboard',c); @@ -702,12 +806,12 @@ function roibar_Buttonup(type) %#ok c{16,2} = gui.sigma; else c{16,1} = 'No smoothing'; -end; +end if get(gui.handles.cropzerocheckbox,'value') c{17,1} = 'Cropping'; else c{17,1} = 'No cropping'; -end; +end for rloop=1:length(gui.rois) c{3,2+(rloop-1)*2} = SET(gui.no).Roi(gui.rois(rloop)).Name; c{4,2+(rloop-1)*2} = 'Value'; @@ -734,7 +838,7 @@ function roibar_Buttonup(type) %#ok c{13,3+(rloop-1)*2} = gui.t(gui.fwhmend(rloop)); c{14,3+(rloop-1)*2} = (gui.centergravity(rloop)-1)*1000*SET(gui.no).TIncr; -end; +end segment('cell2clipboard',c); %---------------------- @@ -761,7 +865,7 @@ function roibar_Buttonup(type) %#ok smoothen = true; else smoothen = false; -end; +end %--------------------------- function datacursor_Callback %#ok diff --git a/source/reportvolume.m b/source/reportvolume.m index 16cf88b..e499259 100644 --- a/source/reportvolume.m +++ b/source/reportvolume.m @@ -11,7 +11,7 @@ function reportvolume(varargin) function curve_Callback(no,path,name) %#ok %-------------------------- %GUI for reporting the volume curve. -global SET NO +global SET NO DATA if nargin == 0 no = NO; @@ -26,7 +26,7 @@ function curve_Callback(no,path,name) %#ok end fig=figure('visible','off'); -set(fig,'Name','Volume curve','numbertitle','off'); +set(fig,'Name',dprintf('Volume curve'),'numbertitle','off'); t = 1000*((0:(SET(no).TSize-1))*SET(no).TIncr); h = plot(t,SET(no).LVV,'r.-'); set(h,'linewidth',2); @@ -37,14 +37,14 @@ function curve_Callback(no,path,name) %#ok % h = plot([t(1) t(end)],[mean(SET(no).EPV-SET(no).LVV) mean(SET(no).EPV-SET(no).LVV)],'g:'); % %set(h,'linewidth',2); % end; -legend('LV volume [ml]','Myocard volume [ml]','Mean myocard volume [ml]','location','SouthEast'); +legend(dprintf('LV volume [ml]'),'location','SouthEast'); %'Myocard volume [ml]','Mean myocard volume [ml]', hold off; grid on; % h = title('Volume versus time');set(h,'fontsize',14); -h = xlabel('Time [ms]'); set(h,'fontsize',14); -h = ylabel('Volume [ml]'); set(h,'fontsize',14); +h = xlabel(dprintf('Time [ms]')); set(h,'fontsize',14); +h = ylabel(dprintf('Volume [ml]')); set(h,'fontsize',14); set(0, 'currentfigure', fig); -currentFolder = pwd; +currentFolder = DATA.SegmentFolder; cd(path) print(fig,'-dpng', name) cd(currentFolder) diff --git a/source/resetgpu.m b/source/resetgpu.m new file mode 100644 index 0000000..8ce48e2 --- /dev/null +++ b/source/resetgpu.m @@ -0,0 +1,30 @@ +function resetgpu +%Resets GPU device and throughs an error message +% +%See also usegpu() + +%Einar Heiberg + +e = lasterror; %#ok + +if strfind(e.message,'Out of memory') + stri1 = 'Out of memory on GPU. Reset GPU. If problem persists try to close 3D view.'; +else + stri1 = 'Unknown GPU error.'; +end + +gpuDevice([]); %deselects and clears its +g = gpuDevice; +stri2 = dprintf('Total GPU memory %0.5g GB. Available GPU memory %0.5g GB',g.TotalMemory/1e9,g.AvailableMemory/1e9); + +stri = [stri1 ' ' stri2]; + +h = msgbox(stri,'GPU error'); + +mydisp(stri); + +try + pause(2); + delete(h); +catch +end diff --git a/source/roi.fig b/source/roi.fig index b6159c0..f10a68a 100644 Binary files a/source/roi.fig and b/source/roi.fig differ diff --git a/source/roi.p b/source/roi.p index 792af10..9590ad6 100644 Binary files a/source/roi.p and b/source/roi.p differ diff --git a/source/rprintf.m b/source/rprintf.m new file mode 100644 index 0000000..69d6a5c --- /dev/null +++ b/source/rprintf.m @@ -0,0 +1,11 @@ +%------------------------------ +function varargout = rprintf(varargin) +%------------------------------ +% special function to translate phrases in report +global DATA +language = DATA.Pref.ReportLanguage; +fromlanguage = 'English'; +if nargin > 0 + varargin{1} = translation.dictionary(varargin{1},language,fromlanguage); +end +[varargout{1:nargout}] = sprintf(varargin{:}); \ No newline at end of file diff --git a/source/rv.p b/source/rv.p index 6618866..dfae40a 100644 Binary files a/source/rv.p and b/source/rv.p differ diff --git a/source/rvsegmentation.fig b/source/rvsegmentation.fig index 7466ffd..fce112a 100644 Binary files a/source/rvsegmentation.fig and b/source/rvsegmentation.fig differ diff --git a/source/rvsegmentation.m b/source/rvsegmentation.m deleted file mode 100644 index 8ca0427..0000000 --- a/source/rvsegmentation.m +++ /dev/null @@ -1,564 +0,0 @@ -function varargout = rvsegmentation(varargin) -%function for initialization of automatic RV segmentation - -macro_helper(varargin{:}); -if nargin < 1 || isempty(varargin{1}) - varargin{1} = 'init'; -end - -[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard - -%------------ -function init -%------------ -%Initialize the GUI - -global DATA SET - -[saxno,~,~,ch4no,success]=lvsegmentation('croplvall',1); - -if not(success) || isempty(saxno) - myfailed('Could not find short-axis image stack for RV analysis.',DATA.GUI.Segment); - return -end - -if SET(saxno).ZSize < 5 - myfailed('Need at least 5 slices for fully automated segmentation.',DATA.GUI.Segment); - return -end - -%Open RV wizard GUI -gui = mygui('rvsegmentation.fig'); -DATA.GUI.RVSegmentation = gui; - -gui.saxno = saxno; -gui.ch4no = ch4no; - -%set ED as current time frame -tools('enddiastole_Callback'); - -%Init time slider -gui.tf = SET(gui.saxno).CurrentTimeFrame; -tsz = SET(gui.saxno).TSize; -if tsz == 1 - set(gui.handles.timebaraxes,'visible','off'); -else - sliderstep = [1/(tsz-1) 5/(tsz-1)]; - set(gui.handles.timeslider,'Min',1,'Max',tsz,'Value',gui.tf, ... - 'SliderStep',sliderstep); - set(gui.handles.timetext,'String',sprintf('%0.0f ms',1000*SET(gui.saxno).TimeVector(gui.tf))); - - load Icons.mat - set(gui.handles.prevpushbutton,'CData',icon.prev); - set(gui.handles.playtogglebutton,'CData',icon.play); - set(gui.handles.nextpushbutton,'CData',icon.next); - inittimebar; -end - -%find lv center -if isempty(SET(gui.saxno).StartSlice) || isempty(SET(gui.saxno).EndSlice) - SET(gui.saxno).StartSlice = round(SET(gui.saxno).ZSize); - SET(gui.saxno).EndSlice = round(SET(gui.saxno).ZSize); -end -if SET(gui.saxno).EndSlice - SET(gui.saxno).StartSlice < 4 - SET(gui.saxno).EndSlice = min([SET(gui.saxno).ZSize ceil(SET(gui.saxno).ZSize*3/4)]); - SET(gui.saxno).StartSlice = max([1 floor(SET(gui.saxno).ZSize/4)]); -end -gui.midslice = floor((SET(gui.saxno).StartSlice + SET(gui.saxno).EndSlice)/2); -[x,y] = findfunctions('findrvcenter',gui.saxno,SET(gui.saxno).StartSlice:SET(gui.saxno).EndSlice); -SET(gui.saxno).CenterX=x; -SET(gui.saxno).CenterY=y; - -[rows,cols] = calcfunctions('calcrowscols',gui.saxno); -gui.matrix = [rows cols]; %viewmatrix for shortaxis image - -gui.saxim = calcfunctions('calcmontageviewim',gui.saxno,gui.matrix); -gui.midim = calcfunctions('remapuint8',SET(gui.saxno).IM(:,:,:,gui.midslice),gui.saxno); -emptyim = uint8(zeros(1,1,SET(gui.saxno).TSize)); -gui.ch4im = emptyim; -if ~isempty(gui.ch4no) - tfs = round(linspace(1,SET(gui.ch4no).TSize,SET(gui.saxno).TSize)); - gui.ch4im = calcfunctions('remapuint8',SET(gui.ch4no).IM(:,:,tfs),gui.ch4no); -end - -%plot sax image stack -gui.handles.saximh = image(gui.saxim(:,:,gui.tf),'Parent',gui.handles.shortaxisaxes); -% gui.handles.midimh = image(gui.midim(:,:,gui.tf),'Parent',gui.handles.midsliceaxes); - -axh = [gui.handles.shortaxisaxes gui.handles.ch4axes]; %gui.handles.midsliceaxes -colormap(axh(1),gray(255)); -colormap(axh(2),gray(255)); -hold(axh(1),'on'); -hold(axh(2),'on'); -set(gui.handles.saximh,'ButtonDownFcn', ... - 'rvsegmentation(''shortaxisaxes_Buttondown'')'); -% set(gui.handles.midimh,'ButtonDownFcn', ... -% 'rvsegmentation(''midsliceaxes_Buttondown'')'); - -%plot long-axis image stacks -if ~isempty(gui.ch4no) -gui.handles.ch4imh = image(gui.ch4im(:,:,gui.tf),'Parent',gui.handles.ch4axes); -colormap(axh(2),gray(255)); -hold(axh(2),'on'); -set(gui.handles.ch4imh,'ButtonDownFcn', ... - 'lvsegmentation(''ch4axes_Buttondown'')'); -else - set(gui.handles.ch4axes,'visible','off'); -end - -axis(axh,'off'); -axis(axh,'equal'); - -%Initiate plot handles -gui.handles.startsliceframe = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.endsliceframe = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.startslice4ch = plot(gui.handles.ch4axes,[],[]); -gui.handles.endslice4ch = plot(gui.handles.ch4axes,[],[]); -gui.handles.centerbasal = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.centerapical = plot(gui.handles.shortaxisaxes,[],[]); -gui.handles.center4ch = plot(gui.handles.ch4axes,[],[]); - -set(gui.fig,'KeyPressFcn', ... - @(hObject,eventdata)rvsegmentation('keypressed',hObject,eventdata)); - -%use user defined sliceselction and centerpoint if it exist -if isfield(SET(gui.saxno),'RV') && ~isempty(SET(gui.saxno).RV) && isfield(SET(gui.saxno).RV,'centerbasal') && ~isempty(SET(gui.saxno).RV.centerbasal) && isfield(SET(gui.saxno).RV,'slicebasal') && ~isempty(SET(gui.saxno).RV.slicebasal) - SET(gui.saxno).StartSlice = SET(gui.saxno).RV.slicebasal; - SET(gui.saxno).EndSlice = SET(gui.saxno).RV.sliceapical; - updateselectedslices; - %calcualte center point for montage view - colbasal = mod(SET(gui.saxno).StartSlice,gui.matrix(2)); - if colbasal == 0, colbasal=gui.matrix(2); end - rowbasal = ceil(SET(gui.saxno).StartSlice/gui.matrix(2)); - colapical = mod(SET(gui.saxno).EndSlice,gui.matrix(2)); - if colapical == 0, colapical=gui.matrix(2); end - rowapical = ceil(SET(gui.saxno).EndSlice/gui.matrix(2)); - xposbasal = round((rowbasal-1)*SET(gui.saxno).XSize)+SET(gui.saxno).RV.centerbasal(1); - yposbasal = round((colbasal-1)*SET(gui.saxno).YSize)+SET(gui.saxno).RV.centerbasal(2); - xposapical = round((rowapical-1)*SET(gui.saxno).XSize)+SET(gui.saxno).RV.centerapical(1); - yposapical= round((colapical-1)*SET(gui.saxno).YSize)+SET(gui.saxno).RV.centerapical(2); - %plot center points - updatecenterpoint(xposbasal,yposbasal,SET(gui.saxno).RV.centerbasal(1),SET(gui.saxno).RV.centerbasal(2),'basal'); - updatecenterpoint(xposapical,yposapical,SET(gui.saxno).RV.centerapical(1),SET(gui.saxno).RV.centerapical(2),'apical'); -else - updateselectedslices; - %default center point - thisslicex = round(0.5*SET(gui.saxno).XSize); - thisslicey = round(0.25*SET(gui.saxno).YSize); - %calcualte center point for montage view - colbasal = mod(SET(gui.saxno).StartSlice,gui.matrix(2)); - if colbasal == 0, colbasal=gui.matrix(2); end - rowbasal = ceil(SET(gui.saxno).StartSlice/gui.matrix(2)); - colapical = mod(SET(gui.saxno).EndSlice,gui.matrix(2)); - if colapical == 0, colapical=gui.matrix(2); end - rowapical = ceil(SET(gui.saxno).EndSlice/gui.matrix(2)); - xposbasal = round((rowbasal-1)*SET(gui.saxno).XSize)+thisslicex; - yposbasal = round((colbasal-1)*SET(gui.saxno).YSize)+thisslicey; - xposapical = round((rowapical-1)*SET(gui.saxno).XSize)+thisslicex; - yposapical= round((colapical-1)*SET(gui.saxno).YSize)+thisslicey; - - SET(gui.saxno).RV.centerbasal = [thisslicex,thisslicey]; - SET(gui.saxno).RV.centerapical = [thisslicex,thisslicey]; - SET(gui.saxno).RV.slicebasal = SET(gui.saxno).StartSlice; - SET(gui.saxno).RV.sliceapical = SET(gui.saxno).EndSlice; - - updatecenterpoint(xposbasal,yposbasal,thisslicex,thisslicey,'basal'); - updatecenterpoint(xposapical,yposapical,thisslicex,thisslicey,'apical'); -end -set(gui.handles.centerbasal,'ButtonDownFcn', ... - 'rvsegmentation(''shortaxisaxes_Buttondown'')'); -set(gui.handles.centerapical,'ButtonDownFcn', ... - 'rvsegmentation(''shortaxisaxes_Buttondown'')'); - -%------------------- -function inittimebar -%------------------- -%Initiate timebar axis -global DATA SET -gui = DATA.GUI.RVSegmentation; - -h = gui.handles.timebaraxes; -no = gui.saxno; -if isempty(no) - return -end -set(h,'ButtonDownFcn', ... - @(hObject,eventdata)rvsegmentation('timebaraxes_ButtonDownFcn',hObject,eventdata)); - -delete(get(h,'Children')); - -tvec = SET(no).TimeVector; - -hold(h,'on'); -fcn = @(hObject,eventdata)rvsegmentation('timebar_ButtonDownFcn',hObject,eventdata); - -%Draw timebar (red) and set its buttondown fcn -gui.handles.timebar = plot(h,tvec(gui.tf)*[1 1],[0 1],'b','Tag','currenttime'); -set(gui.handles.timebar,'ButtonDownFcn',fcn); - -%Set axes options -tvec = SET(no).TimeVector; -tmin = tvec(1); -tmax = tvec(end); - -marg = (tmax-tmin)/500; -axis(h,[tmin-marg tmax+marg 0 1]); -tickvec = tmin:0.2:tmax; -set(h, 'XTick', tickvec,'YTick',[],'XMinorTick','off','XGrid','on', ... - 'XTickLabel',cellfun(@num2str,num2cell(1000*tickvec), ... - 'UniformOutput',false),'TickLength',[0.005 0.025]); - -temp = get(gui.handles.timebaraxes,'ylim'); -ttemp = [tvec;tvec]; -temp = [repmat(temp(1),size(tvec));repmat(temp(1)+0.1*(temp(2)-temp(1)),size(tvec))]; -plot(gui.handles.timebaraxes,ttemp,temp,'k-'); - -updatetimebar; - -%--------------------- -function updatetimebar -%--------------------- -%Update timebar axis -global DATA SET -gui = DATA.GUI.RVSegmentation; - -h = gui.handles.timebaraxes; -no = gui.saxno; -if isempty(no) - return -end - -fcn = get(h,'ButtonDownFcn'); -currenttime = SET(gui.saxno).TimeVector(gui.tf); - -%Update timebar -set(gui.handles.timebar,'XData',currenttime*[1 1]) - -set(h,'ButtonDownFcn',fcn); - - -%--------------------------------------------- -function timebaraxes_ButtonDownFcn(hObject, ~) -%--------------------------------------------- -%Buttondown function for timebar axes. Changes current timeframe to the -%one closest to position of clicked point -global DATA SET -gui = DATA.GUI.RVSegmentation; -no = gui.saxno; -x = mygetcurrentpoint(hObject); -[~,tf] = min(abs(SET(no).TimeVector-x)); -gui.tf = max(min(tf,SET(no).TSize),1); -updateimages; - -%----------------------------------------- -function timebar_ButtonDownFcn(hObject, ~) -%----------------------------------------- -%Buttondown function for graphical timebar object. Activates dragging of timebars. -global DATA -gui = DATA.GUI.RVSegmentation; -no = gui.saxno; -obj = hObject; -motionfcn = @(hObject,eventdata)rvsegmentation('timebaraxes_MotionFcn',hObject,eventdata,obj,no); -set(gui.fig,'WindowButtonMotionFcn',motionfcn); -buttonupfcn = @(hObject,eventdata)rvsegmentation('timebaraxes_ButtonUpFcn',hObject,eventdata); -set(gui.fig,'WindowButtonUpFcn', buttonupfcn); - -%---------------------------------------------- -function timebaraxes_MotionFcn(~, ~, tbobj, no) -%---------------------------------------------- -%Mouse motion function for timebar axes of image specified by input -%parameter 'field'. Used for dragging timebars to change current -%timeframe or start/end points of timeframes in which to align images. -global DATA SET -x = mygetcurrentpoint(get(tbobj,'Parent')); -[~,tf] = min(abs(SET(no).TimeVector-x)); -DATA.GUI.RVSegmentation.tf = max(min(tf,SET(no).TSize),1); -updateimages; - -%------------------------------------------- -function timebaraxes_ButtonUpFcn(hObject, ~) -%------------------------------------------- -%Buttonup function for timebar axes of image specified by input -%parameter 'field'. Deactivates dragging of timebar. -set(hObject,'WindowButtonMotionFcn',[],'WindowButtonUpFcn',[]); - - -%--------------------------- -function timeslider_Callback -%--------------------------- -%Callback for timeslider -global DATA -gui = DATA.GUI.RVSegmentation; - -%Update timeframe and images -gui.tf = round(mygetvalue(gui.handles.timeslider)); -set(gui.handles.timeslider,'Value',gui.tf); -updateimages; - -%-------------------- -function updateimages -%-------------------- -%Update all image stacks and also timebar -global DATA SET -gui = DATA.GUI.RVSegmentation; -set(gui.handles.saximh,'CData',gui.saxim(:,:,gui.tf)); -% set(gui.handles.midimh,'CData',gui.midim(:,:,gui.tf)); -if isfield(gui.handles,'ch4imh') - set(gui.handles.ch4imh,'CData',gui.ch4im(:,:,gui.tf)); -end -set(gui.handles.timetext,'String', ... - sprintf('%0.0f ms',1000*SET(gui.saxno).TimeVector(gui.tf))); -if SET(gui.saxno).TSize > 1 - updatetimebar; -end - -%--------------------- -function prev_Callback -%--------------------- -%Callback for previous timeframe pushbutton -global DATA SET -gui = DATA.GUI.RVSegmentation; -gui.tf = mod(gui.tf-2,SET(gui.saxno).TSize)+1; -updateimages; - -%--------------------- -function next_Callback -%--------------------- -%Callback for next timeframe pushbutton -global DATA SET -gui = DATA.GUI.RVSegmentation; -gui.tf = mod(gui.tf,SET(gui.saxno).TSize)+1; -updateimages; - -%--------------------- -function play_Callback -%--------------------- -%Callback for play togglebutton -global DATA SET -gui = DATA.GUI.RVSegmentation; - -h = gui.handles.playtogglebutton; -no = gui.saxno; -while ishandle(h) && mygetvalue(h) - gui.tf = mod(gui.tf,SET(no).TSize)+1; - set(gui.handles.timeslider,'Value',gui.tf); - updateimages; - %Do pause to release CPU burden. - pause(0.5*SET(no).BeatTime/SET(no).TSize); -end - -%---------------------------- -function updateselectedslices -%---------------------------- -%Draw markers around selected slices -global DATA SET -gui = DATA.GUI.RVSegmentation; - -%Clean up before drawing new frames and lines -delete([gui.handles.startsliceframe gui.handles.endsliceframe ... - gui.handles.startslice4ch gui.handles.endslice4ch]); - -if (SET(gui.saxno).XSize*gui.matrix(1)) < (SET(gui.saxno).YSize*gui.matrix(2)) - scalefactorx = 1;%(SET(gui.saxno).XSize*gui.matrix(1))/(SET(gui.saxno).YSize*gui.matrix(2)); - scalefactory = 1; -else - scalefactorx = 1; - scalefactory = 1;%(SET(gui.saxno).YSize*gui.matrix(2))/(SET(gui.saxno).XSize*gui.matrix(1)); -end -boxx = scalefactorx*[-1 -1 1 1 -1]*SET(gui.saxno).XSize/2+0.5*[1 1 -1 -1 1];%gui.matrix(1); -boxy = scalefactory*[-1 1 1 -1 -1]*SET(gui.saxno).YSize/2+0.5*[1 -1 -1 1 1];%gui.matrix(2); -for slice = unique([SET(gui.saxno).StartSlice SET(gui.saxno).EndSlice]) - row = ceil(slice/gui.matrix(2)); - col = slice-(row-1)*gui.matrix(2); - centerx = (row-0.5)*SET(gui.saxno).XSize+0.5;%;%+1;% - centery = (col-0.5)*SET(gui.saxno).YSize+0.5;%;%+1;% - if slice == SET(gui.saxno).StartSlice - gui.handles.startsliceframe = plot( ... - gui.handles.shortaxisaxes,centery+boxy,centerx+boxx,'b','LineWidth',2); - end - if slice == SET(gui.saxno).EndSlice - gui.handles.endsliceframe = plot( ... - gui.handles.shortaxisaxes,centery+boxy,centerx+boxx,'r','LineWidth',2); - end -end - -if ~isempty(gui.ch4no) - [ssx,ssy] = calcfunctions('calcplaneintersections', ... - gui.ch4no,gui.saxno,'one','one',SET(gui.saxno).StartSlice); - [esx,esy] = calcfunctions('calcplaneintersections', ... - gui.ch4no,gui.saxno,'one','one',SET(gui.saxno).EndSlice); - gui.handles.startslice4ch = plot( ... - gui.handles.ch4axes,ssy,ssx,'b'); - gui.handles.endslice4ch = plot( ... - gui.handles.ch4axes,esy,esx,'r'); -end - -segment('updateselectedslices'); - - -%---------------------------------------------------------------- -function updatecenterpoint(x,y,thisslicex,thisslicey,centerslice) -%---------------------------------------------------------------- -%Update center point -global DATA SET -gui = DATA.GUI.RVSegmentation; - -if nargin < 1 - x = SET(gui.saxno).CenterX; - y = SET(gui.saxno).CenterY; - thisslicex = SET(gui.saxno).CenterX; - thisslicey = SET(gui.saxno).CenterY; - centerslice = 'basal'; -end - -crosscolor = [1 0.6 0.2]; %DATA.centercrossdef -[tempx,tempy] = ndgrid(0:(gui.matrix(1)-1),0:(gui.matrix(2)-1)); -switch centerslice - case 'basal' - %Clean up before drawing - delete(gui.handles.centerbasal); - gui.handles.centerbasal = plot(gui.handles.shortaxisaxes,y,x, ... - '+','color',crosscolor,'LineWidth',3,'MarkerSize',12); - startxyz = [thisslicex;thisslicey;SET(gui.saxno).StartSlice]; - endxyz = [SET(gui.saxno).RV.centerapical(1); SET(gui.saxno).RV.centerapical(2); SET(gui.saxno).EndSlice]; - set(gui.handles.centerbasal,'ButtonDownFcn', ... - 'rvsegmentation(''shortaxisaxes_Buttondown'')'); - case 'apical' - %Clean up before drawing - delete(gui.handles.centerapical); - gui.handles.centerapical = plot(gui.handles.shortaxisaxes,y,x, ... - '+','color',crosscolor,'LineWidth',3,'MarkerSize',12); - startxyz = [SET(gui.saxno).RV.centerbasal(1); SET(gui.saxno).RV.centerbasal(2); SET(gui.saxno).StartSlice]; - endxyz = [thisslicex;thisslicey; SET(gui.saxno).EndSlice]; - set(gui.handles.centerapical,'ButtonDownFcn', ... - 'rvsegmentation(''shortaxisaxes_Buttondown'')'); -end - -%Get center point coordinates in longaxis images -[saxpos,saxmat] = calcfunctions('calcormat',gui.saxno); -truecenter = [saxpos saxpos] + saxmat*([startxyz endxyz]-1); - -if ~isempty(gui.ch4no) - %Clean up before drawing - delete(gui.handles.center4ch); - [ch4pos,ch4mat] = calcfunctions('calcormat',gui.ch4no); - ch4center = 1 + ch4mat\(truecenter - [ch4pos ch4pos]); - gui.handles.center4ch = plot( ... - gui.handles.ch4axes,ch4center(2,:),ch4center(1,:),'Color',crosscolor); -end - -%-------------------------------- -function shortaxisaxes_Buttondown %#ok -%-------------------------------- -global DATA SET -gui = DATA.GUI.RVSegmentation; - -%Extract coordinates clicked -[y,x] = mygetcurrentpoint(gui.handles.shortaxisaxes); -%Find slice -col = 1+floor((y-0.5)/SET(gui.saxno).YSize); -row = 1+floor((x-0.5)/SET(gui.saxno).XSize); -slice = col+(row-1)*gui.matrix(2); - -if slice > SET(gui.saxno).ZSize - return; -end -slicediff = [abs(SET(gui.saxno).StartSlice-slice) abs(SET(gui.saxno).EndSlice-slice)]; -[~,closestslice] = min(slicediff); -switch closestslice - case 1 - SET(gui.saxno).StartSlice = slice; - SET(gui.saxno).RV.slicebasal = slice; - %storing points for usage in RV segmentation - thisslicex = max(1,min(SET(gui.saxno).XSize,round(x-(row-1)*SET(gui.saxno).XSize))); - SET(gui.saxno).RV.centerbasal(1) = thisslicex; - thisslicey = max(1,min(SET(gui.saxno).YSize,round(y-(col-1)*SET(gui.saxno).YSize))); - SET(gui.saxno).RV.centerbasal(2) = thisslicey; - %plot centerpoint - updatecenterpoint(x,y,thisslicex,thisslicey,'basal'); - case 2 - SET(gui.saxno).EndSlice = slice; - SET(gui.saxno).RV.sliceapical= slice; - %storing points for usage in RV segmentation - thisslicex = max(1,min(SET(gui.saxno).XSize,round(x-(row-1)*SET(gui.saxno).XSize))); - SET(gui.saxno).RV.centerapical(1) = thisslicex; - thisslicey = max(1,min(SET(gui.saxno).YSize,round(y-(col-1)*SET(gui.saxno).YSize))); - SET(gui.saxno).RV.centerapical(2) = thisslicey; - %plot centerpoint - updatecenterpoint(x,y,thisslicex,thisslicey,'apical'); -end -updateselectedslices; - - -%------------------------------------- -function keypressed(hObject,eventdata) -%------------------------------------- -%Keypress function for GUI -global DATA SET -gui = DATA.GUI.RVSegmentation; - -switch eventdata.Key -% case 'uparrow' -% if isempty(eventdata.Modifier) -% SET(gui.saxno).StartSlice = max(1,SET(gui.saxno).StartSlice-1); -% else -% SET(gui.saxno).EndSlice = max(SET(gui.saxno).StartSlice,SET(gui.saxno).EndSlice-1); -% end -% updateselectedslices; -% case 'downarrow' -% if isempty(eventdata.Modifier) -% SET(gui.saxno).StartSlice = min(SET(gui.saxno).EndSlice,SET(gui.saxno).StartSlice+1); -% else -% SET(gui.saxno).EndSlice = min(SET(gui.saxno).ZSize,SET(gui.saxno).EndSlice+1); -% end -% updateselectedslices; - case 'leftarrow' - prev_Callback; - case 'rightarrow' - next_Callback; - case 'p' - set(gui.handles.playtogglebutton,'value',1-mygetvalue(gui.handles.playtogglebutton)); - play_Callback; - case 'd' - if get(gui.handles.playtogglebutton,'value') - set(gui.handles.playtogglebutton,'value',0) - play_Callback; - end - gui.tf = SET(gui.saxno).EDT; - updateimages; - case 's' - if get(gui.handles.playtogglebutton,'value') - set(gui.handles.playtogglebutton,'value',0) - play_Callback; - end - gui.tf = SET(gui.saxno).EST; - updateimages; -end - -%--------------------- -function dorv_Callback %#ok -%--------------------- -%Do RV segmentation in selected slices -global DATA -gui = DATA.GUI.RVSegmentation; -segment('switchtoimagestack',gui.saxno); -oldpol=DATA.ThisFrameOnly; -DATA.ThisFrameOnly=0; -rv('segmentrvendo_Callback',0); -close_Callback -drawfunctions('drawall',DATA.ViewMatrix(1),DATA.ViewMatrix(2)); -figure(DATA.GUI.Segment.fig); -DATA.ThisFrameOnly=oldpol; - -%---------------------- -function close_Callback -%---------------------- -%Close RV segmentation GUI -global DATA - -try - DATA.GUI.RVSegmentation = close(DATA.GUI.RVSegmentation); -catch %#ok - DATA.GUI.RVSegmentation=[]; - delete(gcbf); -end diff --git a/source/rvsegmentation.p b/source/rvsegmentation.p new file mode 100644 index 0000000..5fb0743 Binary files /dev/null and b/source/rvsegmentation.p differ diff --git a/source/sectra.p b/source/sectra.p index f595cfd..f4988ee 100644 Binary files a/source/sectra.p and b/source/sectra.p differ diff --git a/source/segdicomfile.m b/source/segdicomfile.m index b81fa80..6cd6c82 100644 --- a/source/segdicomfile.m +++ b/source/segdicomfile.m @@ -5,7 +5,7 @@ %0008,0023 = ContentDate (set to same as studydate) %0008,0030 = StudyTime (from AcquisitionTime) %0008,0033 = ContentTime (set to same as studytime) - %0008,0050 = AccessionNumber (undersökningsnummer) OK. + %0008,0050 = AccessionNumber (unders?kningsnummer) OK. %0020,0010 = StudyID (Remissnummer) methods(Static) % Public @@ -42,8 +42,10 @@ function create(filename, data, study_uid, pat_name, pat_id, ... 'SOPClassUID', 'UI', uint8('1.2.840.10008.5.1.4.1.1.7')); segdicomfile.write_tag(mem, 'SOPInstanceUID', 'UI', instance_uid); segdicomfile.write_tag(mem, 'StudyDate', 'DA', uint8(data(1).PatientInfo.AcquisitionDate)); + segdicomfile.write_tag(mem, 'SeriesDate', 'DA', uint8(datestr(now,'yyyymmdd')));% Jelena: added for OPenApps to distinguish segdicomfile.write_tag(mem, 'ContentDate', 'DA', uint8(data(1).PatientInfo.AcquisitionDate)); segdicomfile.write_tag(mem, 'StudyTime', 'TM', uint8(segdicomfile.secondtostring(data(1).AcquisitionTime))); + segdicomfile.write_tag(mem, 'SeriesTime', 'TM', uint8(datestr(now,'hhMMss.FFF000'))); segdicomfile.write_tag(mem, 'ContentTime', 'TM', uint8(segdicomfile.secondtostring(data(1).AcquisitionTime))); if switchtags segdicomfile.write_tag(mem, 'AccessionNumber', 'SH', uint8(data(1).StudyID)); %StudyID and AccessionNumber are switched in Sectra PACS @@ -97,6 +99,7 @@ function create(filename, data, study_uid, pat_name, pat_id, ... segdicomfile.serialize(data)); segdicomfile.write_tag(mem, ... 'PixelData', 'OW', image); + segdicomfile.write_tag(mem, 'SeriesDescription', 'LO', uint8('SegmCMR_analysis')); end function r = serialize( data ) @@ -209,7 +212,7 @@ function write_tag(mem, tag_name, vr, data) typecast(uint16(length(data)+mod(length(data), 2)), 'uint8')]); mem.add(data); if mod(length(data), 2) ~= 0 - mem.add(uint8(20)); + mem.add(uint8(32)); end case {'DA', 'UL', 'US'} mem.add([segdicomfile.name_to_tag(tag_name) uint8(vr) ... @@ -234,14 +237,17 @@ function write_tag(mem, tag_name, vr, data) tags.ImplementationVersionName = uint8([2 0 19 0 ]); tags.SOPClassUID = uint8([8 0 22 0]); tags.SOPInstanceUID = uint8([8 0 24 0]); - tags.StudyDate = uint8([8 0 32 0]); + tags.StudyDate = uint8([8 0 32 0]); + tags.SeriesDate = uint8([8 0 33 0]);% Jelena: added series date for OpenApps version tags.ContentDate = uint8([8 0 35 0]); tags.StudyTime = uint8([8 0 48 0]); + tags.SeriesTime = uint8([8 0 49 0]);% Jelena: added series time for OpenApps version tags.ContentTime = uint8([8 0 51 0]); tags.AccessionNumber = uint8([8 0 80 0]); tags.Modality = uint8([8 0 96 0]); tags.ConversionType = uint8([8 0 100 0]); tags.ReferringPhysicianName = uint8([8 0 144 0]); + tags.SeriesDescription = uint8([8 0 62 16]);% Jelena: added series description for OpenApps version tags.PatientName = uint8([16 0 16 0]); tags.PatientID = uint8([16 0 32 0]); tags.PatientBirthDate = uint8([16 0 48 0]); @@ -272,6 +278,7 @@ function write_tag(mem, tag_name, vr, data) tags.Manufacturer = uint8([8 0 112 0]); tags.ImageOrientation = uint8([32 0 55 0]); tags.ImagePosition = uint8([32 0 50 0]); + end @@ -455,7 +462,7 @@ function write_tag(mem, tag_name, vr, data) min = floor((t-hour*3600)/60); sec = t-hour*3600-min*60; stri = sprintf('%02d%02d%09.6f',hour,min,sec); - end; + end end end diff --git a/source/segdicomread_mex.mexw32 b/source/segdicomread_mex.mexw32 deleted file mode 100644 index a1afd18..0000000 Binary files a/source/segdicomread_mex.mexw32 and /dev/null differ diff --git a/source/segdicomtags.p b/source/segdicomtags.p index f2c5d2d..b6f7c78 100644 Binary files a/source/segdicomtags.p and b/source/segdicomtags.p differ diff --git a/source/segloader.m b/source/segloader.m index aceb7e9..fbad412 100644 --- a/source/segloader.m +++ b/source/segloader.m @@ -55,7 +55,7 @@ function addmatfile(self, filename) if self.previewmode s = load(filename, '-mat', 'preview', 'info'); end - if not(self.previewmode) || not(isfield(s,'preview')) || not(isfield(s,'info')) + if not(self.previewmode) || not(isfield(s,'preview')) || not(isfield(s,'info')) || isempty(s.preview) s = load(filename, '-mat', 'setstruct'); end catch e @@ -92,33 +92,37 @@ function adddicomfiles(self, filenames) 'Can''t continue loading after multidatafile'); end - % Read the dicoms + % Read the dicoms dicomdata = segdicomtags.readfiles(filenames); - + if numel(dicomdata) == 0 error('SEGMENT:ERROR', 'No data to load'); end % Check if we loaded a segdicom file - allHasSegmentData = 1; - noneHasSegmentData = 1; +% allHasSegmentData = 1; +% noneHasSegmentData = 1; + + hassegmentdata = true(numel(dicomdata),1); for i=1:numel(dicomdata) - if dicomdata(1).hassegmentdata() - noneHasSegmentData = 0; - else - allHasSegmentData = 0; - end - end - + hassegmentdata(i) = dicomdata(i).hassegmentdata(); +% if dicomdata(1).hassegmentdata() +% noneHasSegmentData = 0; +% else +% allHasSegmentData = 0; +% end + end + allHasSegmentData = all(hassegmentdata); + noneHasSegmentData = all(not(hassegmentdata)); if not(allHasSegmentData) && not(noneHasSegmentData) - error('SEGMENT:ERROR', 'Either all files or none should be segdicom files'); + error('SEGMENT:ERROR', 'Either all files or none should be segdicom files'); end if allHasSegmentData && strcmp(self.type, 'empty') self.type = 'set'; self.set = []; for i=1:numel(dicomdata) - self.set = [self.set; dicomdata(i).getsegmentdata()]; + self.set = [self.set ; dicomdata(i).getsegmentdata()]; end return end @@ -149,19 +153,20 @@ function adddicomfiles(self, filenames) end segloaderprogressbar('update', struct('name', 'adddicomsdone')); end - + %----------------------- - function [type, r] = render(self, datapath, cropbox) + function [type, r, ignoreddata] = render(self, datapath, cropbox) %----------------------- % Renders the images in the loader object to a % Preview or a set struct suitable for passing on % to segment.m. + ignoreddata=[]; switch self.type case 'empty' error('SEGMENT:ERROR', 'Can''t render empty loader') - case 'stacks'; + case 'stacks' type = 'stacks'; - r = renderstacks(self, datapath, cropbox); + [r,ignoreddata] = renderstacks(self, datapath, cropbox); case 'set' type = 'set'; r = self.set; @@ -182,7 +187,7 @@ function adddicomfiles(self, filenames) im = self.set(1).IM(:, :, 1, 1); tfrac = self.set(1).AcquisitionTime/(3600*24); acquisitiontime = sprintf('%02.0f:%02.0f:%02.0f',segloader.hour(tfrac),segloader.minute(tfrac),segloader.second(tfrac)); - + [agedigit,ageunit] = calcfunctions('calcagewithunits',segloader.getpreviewdata(self.set(1).PatientInfo, 'Age')); desc = sprintf([... 'Type:%s\n' ... 'Seq:%s\n' ... @@ -193,7 +198,7 @@ function adddicomfiles(self, filenames) 'ID :\t\t%s\n' ... 'BirthDate :\t%s\n' ... 'Sex :\t\t%s\n' ... - 'Age :\t\t%s\n' ... + 'Age :\t\t%s %s\n' ... 'HeartRate :\t%0.5g\n'], ... segloader.getpreviewdata(self.set(1), 'ImageType'), ... segloader.getpreviewdata(self.set(1), 'SequenceName'), ... @@ -206,11 +211,13 @@ function adddicomfiles(self, filenames) segloader.getpreviewdata(... self.set(1).PatientInfo, 'BirthDate'), ... segloader.getpreviewdata(self.set(1).PatientInfo, 'Sex'), ... - segloader.getpreviewdata(self.set(1).PatientInfo, 'Age'), ... + agedigit,ageunit,... + ...segloader.getpreviewdata(self.set(1).PatientInfo, 'Age'), ... segloader.getpreviewdata(... self.set(1).PatientInfo, 'HeartRate') ); else im = self.setpreview; + [agedigit,ageunit] = calcfunctions('calcagewithunits',self.setinfo.Age); desc = sprintf([... 'Type:%s\n' ... 'AcquisitionDate:\t%s\n',... @@ -218,14 +225,14 @@ function adddicomfiles(self, filenames) 'ID :\t\t%s\n' ... 'BirthDate :\t%s\n' ... 'Sex :\t\t%s\n' ... - 'Age :\t\t%s\n'], ... + 'Age :\t\t%s %s\n'], ... self.setinfo.ImageType, ... self.setinfo.AcquisitionDate, ... self.setinfo.Name, ... self.setinfo.ID, ... self.setinfo.BirthDate, ... self.setinfo.Sex, ... - self.setinfo.Age); + agedigit, ageunit); end filetype = self.type; @@ -240,12 +247,13 @@ function adddicomfiles(self, filenames) acquisitiontime = self.dicoms(1).getacquisitiontime(); if not(ischar(acquisitiontime)) acquisitiontime = num2str(acquisitiontime); - end; + end secnbr = str2double(acquisitiontime); hours = floor(secnbr/3600); minutes = floor(mod(secnbr,3600)/60); seconds = floor(mod(secnbr,60)); acquisitiontime = sprintf('%02.0f:%02.0f:%02.0f',hours,minutes,seconds); + [agedigit,ageunit] = calcfunctions('calcagewithunits',patinfo.Age); desc = sprintf([... 'Type:%s\n' ... 'Seq:%s\n' ... @@ -257,7 +265,7 @@ function adddicomfiles(self, filenames) 'ID :\t\t%s\n' ... 'BirthDate :\t%s\n' ... 'Sex :\t\t%s\n' ... - 'Age :\t\t%d\n' ... + 'Age :\t\t%d %s\n' ... 'HeartRate :\t%0.5g\n'], ... self.dicoms(1).getimagetype(), ... self.dicoms(1).getsequencename(), ... @@ -269,7 +277,8 @@ function adddicomfiles(self, filenames) patinfo.ID, ... patinfo.BirthDate, ... patinfo.Sex, ... - patinfo.Age, ... + agedigit,ageunit,... + ...patinfo.Age, ... self.dicoms(1).getheartrate() ); filetype = self.type; @@ -290,12 +299,13 @@ function adddicomfiles(self, filenames) methods (Access = private) %----------------------- - function r = renderstacks(self, datapath, cropbox) + function [r, ignoreddata] = renderstacks(self, datapath, cropbox) %----------------------- % This rendering method is used when the files loaded are % dicom files. It's called from the render method. % Init rawstacks + ignoreddata=[]; lines = self.uniquelines(); [itis, imaxis] = self.isrotated; if itis @@ -319,7 +329,12 @@ function adddicomfiles(self, filenames) segloaderprogressbar('update', struct('name', 'sort')); curdicoms = segloader.removeduplicates(curdicoms); curstack.setdicoms(curdicoms); - r = [r curstack.render( datapath, cropbox )]; + [stack, excludecurrent]=curstack.render( datapath, cropbox); + if ~isempty(stack) + r = [r stack]; %#ok + else + ignoreddata=[ignoreddata; string(excludecurrent)]; %#ok + end clear curstack; segloaderprogressbar('update', struct('name', 'renderstack')); end @@ -403,7 +418,7 @@ function adddicomfiles(self, filenames) r = []; for i=1:numel(self.dicoms) r(end+1, :) = self.dicoms(i).getnormal(); - end; + end % Sort it r = sortrows(r); @@ -429,7 +444,7 @@ function adddicomfiles(self, filenames) % imageposition onto the subspaces that the orientation vectors % span. We need this projection to separate projection to % separate stacks with the same orientation but diffrent positions. - r = struct('orientation', {}, 'linepos', {}); + r = struct('orientation',{}, 'linepos',{}, 'seq',{},'type',{}); segloaderprogressbar('update', struct('name', 'uniquelinesstart', ... 'numdicoms', numel(self.dicoms))); @@ -514,6 +529,24 @@ function adddicomfiles(self, filenames) if norm(line1.linepos - line2.linepos) > 2 %changed from 10 NL return end + if ~strcmp(line1.seq, line2.seq) %not equal sequence name + if ~isapproxequal(norm(line1.linepos - line2.linepos),0) + %different sequence name and there is position difference + return + end + if strcmp(line1.type, line2.type) + return + end + end + + if ~strcmp(line1.type, line2.type) %not equal image type + %exlusion for Phase Contrast stacks + if ~cellfun(@(x,y) (contains(x,{'\M\','PCA/M','M\FFE','T1\NONE'})) && (contains(y,{'\P\','PCA/P','VELOCITY\NONE'})) || (contains(y,{'\M\','PCA/M','M\FFE','T1\NONE'})) && (contains(x,{'\P\','PCA/P','VELOCITY\NONE'})),{line1.type},{line2.type}) + return +% elseif cellfun(@(x,y)(contains(x,{'\M\IR','\CR\IR','\M\FFE',}) && contains(y,{'\M\IR','\CR\IR','\M\FFE'})),{line1.type},{line2.type}) %PSIR PHILIPS +% return + end + end eq = true; end @@ -531,7 +564,7 @@ function adddicomfiles(self, filenames) % Convert from tfrac to minutes tfrac = tfrac-segloader.hour(tfrac)/24; m = floor(tfrac*24*60); - end; + end %----------------------- function s = second(tfrac) diff --git a/source/segloaderprogressbar.m b/source/segloaderprogressbar.m index d3f21a8..6d7aa15 100644 --- a/source/segloaderprogressbar.m +++ b/source/segloaderprogressbar.m @@ -1,5 +1,5 @@ function segloaderprogressbar(action, event) - global DATA; + persistent wb; switch action @@ -19,7 +19,7 @@ function segloaderprogressbar(action, event) function wb = segloaderprogressbarinit() wb = struct(); - wb.h = waitbar(0,translation.dictionary('Loading files...')); + wb.h = waitbar(0,dprintf('Loading files...')); wb.filesToRead = []; wb.filesRead = 0; wb.lastWbValue = 0; diff --git a/source/segment.fig b/source/segment.fig index 986b490..5e716fc 100644 Binary files a/source/segment.fig and b/source/segment.fig differ diff --git a/source/segment.m b/source/segment.m index 097021a..d4e024d 100644 --- a/source/segment.m +++ b/source/segment.m @@ -1,9 +1,9 @@ +function varargout = segment(varargin) %This is a script that passes calls of segment(fcnname,arg1,arg2...) to the %object DATA, if the method fcnname exists. If the method does not exist, %the function fcnname is called from segment_main.m, which is the file %previously known as segment.m. -function varargout = segment(varargin) global DATA if nargin < 1 [varargout{1:nargout}] = segment_main; diff --git a/source/segment3dpimage.png b/source/segment3dpimage.png new file mode 100644 index 0000000..c584607 Binary files /dev/null and b/source/segment3dpimage.png differ diff --git a/source/segment_main.m b/source/segment_main.m index 3b4b32a..ecda60d 100644 --- a/source/segment_main.m +++ b/source/segment_main.m @@ -19,12 +19,7 @@ end end -if nargin == 0 || fileinput % LAUNCH and initalize GUI - - % Fix path - if isdeployed() && isequal(mexext(), 'mexmaci64') - cd(getapppath()); - end +if nargin == 0 || fileinput % LAUNCH and initalize GUI %Check if os is supported arch = mexext(); @@ -32,11 +27,28 @@ case {'mexglx','mexmaci','mexmaci64'} myfailed('Your platform is not supported. Supported platforms are Windows and Linux 64 bit.'); return; - end; + end + + if not(isdeployed()) + %source code version, check matlab version + try + matlabversion = ver; + [toolboxindex] = find(ismember({matlabversion.Name},'MATLAB')); + if isempty(toolboxindex), toolboxindex=1; end + if not(strcmp(matlabversion(toolboxindex).Release,'(R2019a)')) + myfailed(sprintf('Recommended Matlab version for Segment is R2019a.\nPlease use this version for best performance of Segment.\nVersions prior to Matlab 2015a will NOT work for this version of Segment.')); + end + catch + end + end programversion = changelog; fig = initializesegment(programversion); %Program version number - + try + compilerpragmas; + catch + end + varargout = cell(1,nargout); if nargout>0 varargout{1} = fig; @@ -62,24 +74,24 @@ if isa(DATA,'maingui') try - mydisp('Already running.'); + disp('Already running.'); if ~isempty(DATA.fig) figure(DATA.fig); fig = DATA.fig; return; else fig = []; - end; + end catch me disp('Program not aborted properly last time, all data will be lost and program restarted.'); mydispexception(me); - end; -end; + end +end %--- Find source if isdeployed() %Compiled version - disp('Standalone'); + disp('Standalone'); else %Check if platform is supported. ext = mexext; @@ -88,8 +100,8 @@ for loop = 1:length(all) if isequal(ext,all(loop).ext) arch = all(loop).arch; - end; - end; + end + end switch arch case {'mac','sol64','glnx86'} @@ -97,27 +109,43 @@ return; otherwise disp(['Running from Matlab on platform ' arch '.']); - end; + end %Do nothing -end; +end %Make sure fresh start DATA = []; %#ok SET = []; %#ok -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%This is where we create object%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%This is where we create object DATA = segmentgui(programversion);%Load standard Segment GUI +DATA.GUISettings.ShowColorbar = false; %until the colorbar is impelemented + +% Register where segment.m is located and if we are running from source +if isdeployed() + [status, result] = system('set PATH'); + pathname = char(regexpi(result, 'Path=(.*?);', 'tokens', 'once')); + DATA.SegmentFolder=pathname; + cd(pathname); +else + [segmentfolder_, ~, ~] = fileparts(which('segment')); + DATA.SegmentFolder = segmentfolder_; + clear segmentfolder_ +end + DATA.init; + try fig = DATA.fig; catch + disp('Software initialization aborted') fig = []; + return end -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +checkpath(DATA.SegmentFolder); %ensure running on correct path + %--------------------- function resetpreview %#ok @@ -128,26 +156,7 @@ DATA.Preview = genemptypreview(DATA.Pref.datapath); - - %----------------------------- - function framemode_Callback(type) - %----------------------------- - %If type 1 we have pressed the single frame mode button type 2 the multi frame mode button - global DATA - singlebutton=DATA.Handles.singleframemodepushbutton; - multibutton=DATA.Handles.multiframemodepushbutton; - switch type - case 1 - set(singlebutton, 'backgroundcolor','g'); - set(multibutton, 'backgroundcolor',[0.8 0.8 0.8]); - DATA.thisframeonly_Callback(1) - case 2 - set(singlebutton, 'backgroundcolor',[0.8 0.8 0.8]); - set(multibutton, 'backgroundcolor','g'); - DATA.thisframeonly_Callback(0) - end - - %--------------------------------- +%--------------------------------- function preview = genemptypreview(datapath) %--------------------------------- %Generate an empty preview struct @@ -157,12 +166,12 @@ function framemode_Callback(type) try %inside try catch if DATA is not set. if isempty(DATA.Preview) || isempty(DATA.Preview.ROISize) - roisize = 150; + roisize = 'full'; %150; else roisize = DATA.Preview.ROISize; end catch -end; +end preview = []; preview.PathName = datapath; @@ -238,15 +247,15 @@ function framemode_Callback(type) if ~exist('pluginfiles','var') myfailed('Problems reading file containing plugins.'); return; - end; + end else %Use filenames f = dir([DATA.SegmentFolder filesep 'plugin_*.m']); pluginfiles = cell(1,length(f)); for loop=1:length(f) pluginfiles{loop} = f(loop).name; - end; -end; + end +end %Initialize menus for loop=1:length(pluginfiles) @@ -257,296 +266,17 @@ function framemode_Callback(type) 'Callback',''); namestri = feval(stri,'getname',handle); set(handle,'Label',namestri); -end; - -%------------------------------------------------------------ -function addviewicon_helper(callback,tooltip,cdata,tag,separator) -%------------------------------------------------------------ -%Helper fcn to add an icon -global DATA - -if nargin<4 - myfailed('Too few input arguments.', DATA.GUI.Segment); - return; -end; - -if nargin<5 - separator = 'off'; -end; - -props = []; -props.ClickedCallback = callback; -props.ToolTip = tooltip; -props.Tag = tag; -props.CData = cdata; -props.Separator = separator; -DATA.Handles.(tag) = uitoggletool(DATA.Handles.viewtoolbar,props); - -%------------------------------------- -function iconhandles = initviewtoolbar %#ok -%------------------------------------- -%Initalize view toolbar -global DATA - -if nargout > 0 - %Return names of handles, for use in killhandles function - %If new handles are added, add those to this list as well! - iconhandles = {'viewtoolbar' - 'previousallframeicon' - 'previousframeicon' - 'playmovieicon' - 'playallicon' - 'nextframeicon' - 'nextallframeicon' - 'fasterframerateicon' - 'slowerframerateicon' - 'cinetoolicon' - 'viewoneicon' - 'mmodeviewicon' - 'viewallicon' - 'montagerowicon' - 'montagefiticon' - 'orthoviewicon' - 'viewzoominicon' - 'viewzoomouticon' - 'refreshicon' - 'resetlighticon' - 'autocontrasticon' - 'undosegmentationicon' - 'imageinfoicon' - 'patientinfoicon' - 'reportsheeticon' - 'movierecordericon' - 'screenshoticon' - 'generalsegmenticon' - 'mpricon' - 'fusionicon' - 'model3icon' - 'volrendicon' - 'reportpersliceicon' - 'reportbullseyeicon' - 'reportlongaxisicon' - 'reportflowicon'}; - return; end -%Create menubar -DATA.Handles.viewtoolbar = uitoolbar(DATA.imagefig); - -%previous all frame icon -addviewicon_helper('segment(''previousallframe_Callback'')',... - 'Previous frame (all image stacks)',... - DATA.Icons.prevall,... - 'previousallframeicon'); - -%previous frame icon -addviewicon_helper('segment(''previousframe_Callback'')',... - 'Previous frame',... - DATA.Icons.prev,... - 'previousframeicon'); - -%Play icon -addviewicon_helper('segment(''playmovie_Callback'')',... - 'Play current image stack',... - DATA.Icons.play,... - 'playmovieicon'); - -%Playall icon -addviewicon_helper('segment(''playall_Callback'')',... - 'Play all visible image stacks',... - DATA.Icons.playall,... -'playallicon'); - -%Next frame icon -addviewicon_helper('segment(''nextframe_Callback'')',... - 'Next frame',... - DATA.Icons.next,... - 'nextframeicon'); - -%Next all frame icon -addviewicon_helper('segment(''nextallframe_Callback'')',... - 'Next frame (all image stacks)',... - DATA.Icons.nextall,... -'nextallframeicon'); - -%Faster framerate icon -addviewicon_helper('segment(''fasterframerate_Callback'')',... - 'Faster frame rate',... - DATA.Icons.faster,... - 'fasterframerateicon'); - -%Slower framerate icon -addviewicon_helper('segment(''slowerframerate_Callback'')',... - 'Slower frame rate',... - DATA.Icons.slower,... - 'slowerframerateicon'); - -%Slower framerate icon -addviewicon_helper('segment(''cinetool_Callback'')',... - 'Make thumbnail cine loop (hot key (c) )',... - DATA.Icons.cinetool,... - 'cinetoolicon'); - -%view one slice -addviewicon_helper('segment(''viewimage_Callback'',''one'')',... - 'View one slice. Hot key to toogle between one slice and montage is (v)',... - DATA.Icons.viewone,... - 'viewoneicon',... - 'on'); - -%mmodeview icon -addviewicon_helper('segment(''viewimage_Callback'',''mmode'')',... -'Mmode view',... -DATA.Icons.mmodeview,... -'mmodeviewicon'); - -%View all icon -addviewicon_helper('segment(''viewimage_Callback'',''montage'')',... - 'View all slices. Hot key to toogle between one slice and montage is (v)',... - DATA.Icons.viewall,... - 'viewallicon'); - -%View montage row -addviewicon_helper('segment(''viewimage_Callback'',''montagerow'')',... - 'View all slices by rows',... - DATA.Icons.montagerow,... - 'montagerowicon'); - -%View montage fit -addviewicon_helper('segment(''viewimage_Callback'',''montagefit'')',... - 'View all slices in one row/column',... - DATA.Icons.montagefit,... - 'montagefiticon'); - -%View orthogonally -addviewicon_helper('segment(''orthoview'')',... - 'View image in orthogonal view planes',... - DATA.Icons.orthoview,... - 'orthoviewicon'); - -%zoom in icon -addviewicon_helper('segment(''viewzoomin_Callback'')',... -'Zoom in',... -DATA.Icons.zoomin,... -'viewzoominicon'); - -%zoom out icon -addviewicon_helper('segment(''viewzoomout_Callback'')',... - 'Zoom out',... - DATA.Icons.zoomout,... - 'viewzoomouticon'); - -%refresh -addviewicon_helper('segment(''viewrefreshall_Callback'')',... - 'Refresh image',... - DATA.Icons.refresh,... - 'refreshicon'); - -%resetlight -addviewicon_helper('segment(''resetlight_Callback'')',... - 'Reset light/contrast',... - DATA.Icons.resetlight,... - 'resetlighticon'); - -%autocontrast -addviewicon_helper('segment(''autocontrast_Callback'')',... - 'Auto contrast',... - DATA.Icons.autocontrast,... - 'autocontrasticon'); - -%undosegmentationicon -addviewicon_helper('tools(''undosegmentation_Callback'')',... - 'Undo latest segmentation, and pin placement(s)',... - DATA.Icons.undo,... - 'undosegmentationicon'); - -%image information -addviewicon_helper('tools(''imageinfo_Callback'')',... - 'Show image stack details',... - DATA.Icons.imageinfo,... - 'imageinfoicon',... - 'on'); - -%patient info -addviewicon_helper('tools(''viewpatientinfo_Callback'')',... - 'View patient details',... - DATA.Icons.patientinfo,... - 'patientinfoicon'); - -%report sheet -addviewicon_helper('reporter.reportsheet',... - 'Create text report sheet',... - DATA.Icons.reportsheet,... - 'reportsheeticon'); - -%screenshot -addviewicon_helper('export(''screenshot_Callback'')',... - 'Save screenshot',... - DATA.Icons.screenshot,... - 'screenshoticon'); - -%movierecorder -addviewicon_helper('export(''exportmovierecorder_Callback'')',... - 'Movie recorder',... - DATA.Icons.movie,... - 'movierecordericon'); - -%general segmentation tool -addviewicon_helper('levelset',... -'General segmentation tool and orthogonal view',... -DATA.Icons.generalsegment,... -'generalsegmenticon'); - -%mpr -addviewicon_helper('reformater',... - 'MPR (Multiple planar reconstruction)',... - DATA.Icons.mpr,... - 'mpricon'); - -%fusion -addviewicon_helper('fusion',... - 'Image fusion',... - DATA.Icons.fusion,... - 'fusionicon'); - -%3dmodel icon -addviewicon_helper('report3dmodel',... - 'View 3d model',... - DATA.Icons.model3,... - 'model3icon'); - -%volumerendering icon -addviewicon_helper('volumerender',... - 'Volume rendering',... - DATA.Icons.volrend,... - 'volrendicon'); - -%reportperslice -addviewicon_helper('slicereport',... - 'Report wall motion per slice',... - DATA.Icons.reportperslice,... - 'reportpersliceicon'); - -%bullseyeicon -addviewicon_helper('reportbullseye',... -'Bulls eye plot',... -DATA.Icons.bullseye,... -'reportbullseyeicon'); - -% %Longaxis report -% addviewicon_helper('longaxisplot',... -% 'Long axis sector report',... -% DATA.Icons.reportlongaxis,... -% 'reportlongaxisicon'); - -%report flow icon -addviewicon_helper('reportflow',... -'Plot flow (Ctrl-T)',... -DATA.Icons.plotflow,... -'reportflowicon'); +%-------------------------------- +function singleframemode_Callback %#ok +%-------------------------------- +%define if single (one) or all frames mode +global DATA +DATA.ThisFrameOnly = not(DATA.Handles.configiconholder.findindented('selectoneall')); %-------------------------- -function cinetool_Callback +function cinetool_Callback %#ok %-------------------------- %Starts the cinetool that allows simultanues segmentation at the %same time as it plays. @@ -555,12 +285,13 @@ function addviewicon_helper(callback,tooltip,cdata,tag,separator) if SET(NO).TSize==1 try %icon might be there and might not - stateandicon=segment('iconson','cineplay'); + stateandicon=viewfunctions('iconson','cineplay'); stateandicon{2}.isindented=0; stateandicon{2}.cdataDisplay=stateandicon{2}.cdata; DATA.Handles.configiconholder.render catch end + myfailed('Need a timeresolved image stack.') return; end @@ -568,105 +299,25 @@ function addviewicon_helper(callback,tooltip,cdata,tag,separator) cinewindow('update','kill'); try %icon might be there and might not - stateandicon=segment('iconson','cineplay'); + stateandicon=viewfunctions('iconson','cineplay'); stateandicon{2}.isindented=0; stateandicon{2}.cdataDisplay=stateandicon{2}.cdata; DATA.Handles.configiconholder.render catch end - %set(DATA.Handles.cinetoolicon,'state','off'); else - %set(DATA.Handles.cinetoolicon,'state','on'); try %icon might be there and might not - stateandicon=segment('iconson','cineplay'); + stateandicon=viewfunctions('iconson','cineplay'); stateandicon{2}.isindented=1; stateandicon{2}.cdataDisplay=stateandicon{2}.cdataIndent; DATA.Handles.configiconholder.render catch end cinewindow; -end; - - -%--------------------------------------------- -function killbuttondown=switchtopanel(panel,updateimagestack) -%--------------------------------------------- -%Make panel the currentpanel -global DATA SET NO - -killbuttondown=0; - -if isempty(panel) - return -end - -if DATA.Silent - return; -end; - -if panel==DATA.CurrentPanel - return; -end; - -if nargin < 2 - updateimagestack = true; -end - -%Make panel current panel -DATA.CurrentPanel = panel; - -%Make sure the current image stack, runs updateviewicons -if updateimagestack - if DATA.CurrentPanel>length(DATA.ViewPanels) - DATA.CurrentPanel=length(DATA.ViewPanels); - end - DATA.switchtoimagestack(DATA.ViewPanels(DATA.CurrentPanel)); -end -%Make all black, one highlighted -set(DATA.Handles.imageaxes,... - 'xcolor',[0 0 0],'ycolor',[0 0 0],... - 'linewidth',0.5,... - 'visible','off'); -set(DATA.Handles.imageaxes(DATA.CurrentPanel),... - 'xcolor',DATA.GUISettings.AxesColor,'ycolor',DATA.GUISettings.AxesColor,... - 'linewidth',2.5,... - 'visible','on'); - -updateselectedslices - -switch DATA.ViewPanelsType{DATA.CurrentPanel} - case 'sag3DP' - SET(NO).LevelSet.Pen.Color = 'g'; - drawfunctions('supdate') - case 'cor3DP' - SET(NO).LevelSet.Pen.Color = 'b'; - drawfunctions('supdate') - case 'trans3DP' - SET(NO).LevelSet.Pen.Color = 'r'; - drawfunctions('supdate') end -%Update intersection lines -drawfunctions('drawintersections'); - -%if any drawing tool or crop tool is selcted, change to pointer and do not -%perform any drawing or cropping - -switch DATA.CurrentTool - case {'drawendo','drawepi','drawrvendo','drawrvepi',... - 'interpendo','interpepi','interprvendo','interprvepi',... - 'drawmarpen','drawmarrubberpen','drawmarrubber',... - 'drawroi','putroi','crop'} - killbuttondown=1; -end - -DATA.updateaxestables('measure'); -DATA.updateaxestables('volume'); -DATA.updateaxestables('flow'); - - %---------------------------- -function addtopanels(no,mode) +function addtopanels(no,mode) %#ok %---------------------------- %Finds an open space, otherwise increases number of panels @@ -682,8 +333,8 @@ function addtopanels(no,mode) mode = 'montage'; else mode = 'one'; - end; -end; + end +end %--- if space exists then add it temp = find(DATA.ViewPanels==0); @@ -692,7 +343,7 @@ function addtopanels(no,mode) DATA.ViewPanelsType{temp(1)} = mode; DATA.ViewIM{temp(1)} = []; return; -end; +end %--- if space does not exist then add DATA.ViewPanels = [DATA.ViewPanels no]; @@ -701,23 +352,6 @@ function addtopanels(no,mode) DATA.ViewPanelsMatrix = [DATA.ViewPanelsMatrix {[rows cols]}]; DATA.ViewIM{length(DATA.ViewPanels)} = []; -%--------------------------------------- -function viewimagestackas_Callback(mode) %#ok -%--------------------------------------- -%Select how to view current image stack -global NO - -if nargin<1 - mode = 'one'; -end; - -%Get clicked coordinate -%no = getclickedpreview;%not necessary since when clicking preview -%DATA.switchtoimagestack is called - -addtopanels(NO,mode) -drawfunctions('drawall'); - %--------------------------- function mainresize_Callback %#ok %--------------------------- @@ -728,7 +362,7 @@ function viewimagestackas_Callback(mode) %#ok %This prevents validate callbacks from reporting error when opening %segment.fig for inspection. return; -end; +end try if isfield(DATA.GUI,'Segment') @@ -787,22 +421,30 @@ function viewimagestackas_Callback(mode) %#ok DATA.GUISettings.RightGapWidth = rpwidth/pfig(3); %Render iconplaceholders aswell - DATA.Handles.toggleiconholder.render + DATA.Handles.toggleiconholder.render + if not(contains(DATA.ProgramName,'3D')) DATA.Handles.permanenticonholder.render - - if ~isempty(DATA.Handles.configiconholder.cdata) - DATA.Handles.configiconholder.render - end - - if ~isempty(DATA.Handles.hideiconholder.cdata) + if ~isempty(DATA.Handles.hideiconholder.cdata) DATA.Handles.hideiconholder.render end + end + + if ~isempty(DATA.Handles.configiconholder.cdata) + DATA.Handles.configiconholder.render + end try - rows=DATA.ViewMatrix(1); - cols=DATA.ViewMatrix(2); - drawfunctions('drawall',rows,cols); - catch + if ~isempty(DATA.ViewMatrix) + rows=DATA.ViewMatrix(1); + cols=DATA.ViewMatrix(2); + if length(DATA.ViewPanelsType) == 4 && all(strcmp(DATA.ViewPanelsType, {'orth', 'hla', 'vla', 'gla'})) + viewfunctions('setview',rows,cols,DATA.ViewPanels,DATA.ViewPanelsType); + else + viewfunctions('setview',rows,cols); %drawfunctions('drawall',rows,cols); + end + end + catch me + mydispexception(me) DATA.Handles.toggleiconholder.render DATA.Handles.permanenticonholder.render if ~isempty(DATA.Handles.configiconholder.cdata) @@ -814,8 +456,8 @@ function viewimagestackas_Callback(mode) %#ok %Mainresize is called uponloading when .fig is not initialized. disp('Could not do mainresize'); mydispexception(me); - end; -end; + end +end %--------------------------------- function renderstacksfromdicom(no) %#ok @@ -826,6 +468,8 @@ function renderstacksfromdicom(no) %#ok %Do not mess with .Silent here since it will be taken care of by lower %routine images. +%New routine doesnt need this function perhaps + global DATA SET if ~DATA.Silent @@ -844,10 +488,7 @@ function renderstacksfromdicom(no) %#ok end [rows1,cols1] = calcfunctions('calcrowscols',1,SET(1).ZSize); [rows2,cols2] = calcfunctions('calcrowscols',2,SET(2).ZSize); - DATA.ViewPanelsMatrix = {[rows1 cols1] [rows2 cols2]}; - - makeviewim(1,1); - makeviewim(2,2); + DATA.ViewPanelsMatrix = {[cols1 rows1] [cols2 rows2]}; else DATA.ViewPanels=1; if (SET(no).ZSize==1) @@ -855,35 +496,30 @@ function renderstacksfromdicom(no) %#ok else DATA.ViewPanelsType{1} = DATA.GUISettings.ViewPanelsTypeDefault; end - [rows,cols] = calcfunctions('calcrowscols',1,SET(1).ZSize); - DATA.ViewPanelsMatrix = {[rows cols]}; + if strcmp(DATA.ViewPanelsType,'montage') + [rows,cols] = calcfunctions('calcrowscols',1,SET(1).ZSize); + else + rows = 1; + cols = 1; + end + DATA.ViewPanelsMatrix = {[cols rows]}; DATA.ViewMatrix=[1 1]; - makeviewim(DATA.CurrentPanel,no); end end - if (~DATA.Preview.Silent) - %Normal loading - - DATA.switchtoimagestack(no,true); %force - drawfunctions('drawthumbnails',isempty(DATA.DATASETPREVIEW)); - drawfunctions('drawall',DATA.ViewMatrix); - %Ensure correct light settings. - %resetlight_Callback; - elseif (length(SET)==1) - DATA.switchtoimagestack(no,true); %force - drawfunctions('drawthumbnails',isempty(DATA.DATASETPREVIEW)); - drawfunctions('drawall',1); - else - DATA.switchtoimagestack(no,true); %force - drawfunctions('drawthumbnails',isempty(DATA.DATASETPREVIEW)); - drawfunctions('drawall',DATA.ViewMatrix); - end; +% if (~DATA.Preview.Silent) +% %Normal loading +% +% %DATA.switchtoimagestack(no,true); %force +% %drawfunctions('drawthumbnails',isempty(DATA.DATASETPREVIEW)); +% +% %The refresh starts everything +% %viewfunctions('setview',DATA.ViewMatrix(1),DATA.ViewMatrix(2)) +% end; + +end -end; -%Not great position as it triggers for ever stack -%DATA.dataloadedplaceholders -mydisp('Files loaded.'); +disp('Files loaded.'); %endoffcalculation; @@ -893,10 +529,14 @@ function update_thumbnail(nos) %This fcn updates thumbnail no global DATA SET +%if DATA.Silent +% return +%end + %Check if empty DATASETPREVIEW and generate if so. if isempty(DATA.DATASETPREVIEW) calcfunctions('calcdatasetpreview'); -end; +end for loop = 1:length(nos) no = nos(loop); @@ -920,9 +560,11 @@ function update_thumbnail(nos) %Store, vertically DATA.DATASETPREVIEW((no-1)*DATA.GUISettings.ThumbnailSize+(1:DATA.GUISettings.ThumbnailSize),:,:) = tempim; -end; +end -set(DATA.Handles.datasetpreviewimage,'cdata',DATA.DATASETPREVIEW); +if ~DATA.Silent + set(DATA.Handles.datasetpreviewimage,'cdata',DATA.DATASETPREVIEW); +end %--------------------------- function out=thumbnailno(in) @@ -932,7 +574,7 @@ function update_thumbnail(nos) if nargin==1 no = in; -end; +end out = no; %----------------------------- @@ -968,6 +610,10 @@ function update_thumbnail(nos) delete(DATA.Handles.thumbnaildragaxes); catch %#ok end + + %then we want the fig position + [x,y] = mygetcurrentpoint(DATA.fig); + DATA.Handles.thumbnaildragaxes = axes(... 'unit','pixels',... 'position',... @@ -988,16 +634,26 @@ function update_thumbnail(nos) case 'alt' %---Right mouse click %Get clicked coordinate - no=getclickedpreview; - - DATA.switchtoimagestack(no); + %Set up + set(DATA.fig,'WindowButtonUpFcn',... + 'segment(''thumbnail_Buttonup'')'); + %Get clicked position + [x,y] = mygetcurrentpoint(DATA.Handles.datasetaxes); + + %Find clicked image stack + no = getclickedpreview(x,y); + thumbnailno(no); %store + + %add no in DATA.lastobject field so that it can be loaded into panels + %if user clicks this + DATA.LastObject = no; %Bring up popup menu [p(1),p(2)] = mygetcurrentpoint(DATA.fig); set(DATA.Handles.datasetpreviewmenu,... 'Position',p,... 'Visible','on'); -end; +end %------------------------ function thumbnail_Motion %#ok @@ -1015,7 +671,7 @@ function update_thumbnail(nos) function thumbnail_Buttonup %#ok %-------------------------- %Buttonup fcn for thumbnails. -global DATA SET NO +global DATA NO %Get coordinate [x,y] = mygetcurrentpoint(DATA.Handles.boxaxes); @@ -1025,7 +681,7 @@ function update_thumbnail(nos) %Restore motion etc set(DATA.fig,'WindowButtonMotionFcn',@DATA.toggleplaceholdermotion); -set(DATA.fig,'WindowButtonUpFcn','segment(''buttonup_Callback'')'); +set(DATA.fig,'WindowButtonUpFcn','buttonupfunctions(''buttonup_Callback'')'); %Hide the image try delete(DATA.Handles.thumbnaildragaxes); @@ -1042,211 +698,52 @@ function update_thumbnail(nos) elseif (x < 0) allreadyout=find(DATA.ViewPanels==no); if ~isempty(allreadyout) - switchtopanel(allreadyout(1)); + viewfunctions('switchpanel',allreadyout(1)); return; end - ind=find(DATA.ViewPanels==0,1); + ind = find(DATA.ViewPanels==0,1); else if strcmp(DATA.CurrentTheme,'3dp') %If in 3dp mode disperse the image according to current view. + + DATA.LevelSet = []; + + segment3dp.tools('check3dpfields'); segment3dp.tools('storetoobject'); - oldno=NO; - NO=no; + oldno = NO; + NO = no; ok = segment3dp.tools('init3DP',0,1); if ~ok - NO=oldno; - end - if DATA.Handles.configiconholder.findindented('viewcoronal') - drawfunctions('corspeed_view') - elseif DATA.Handles.configiconholder.findindented('viewsagittal') - drawfunctions('sagspeed_view') - elseif DATA.Handles.configiconholder.findindented('viewtransversal') - drawfunctions('transspeed_view') - else - drawfunctions('tssc_view') + NO = oldno; end + + segment3dp.tools('update3DP'); + drawfunctions('drawthumbnailframes') return - elseif strcmp(DATA.ViewPanelsType{1},'ortho') + elseif strcmp(DATA.ViewPanelsType{1},'orth') %then we switch to single view mode - NO=no; - drawfunctions('drawimageview',no,[1 1],{'one'}); - undent(DATA.Handles.permanenticonholder,'orthoview',0) + viewfunctions('setview',1, 1, no,{'one'}); + drawfunctions('drawthumbnailframes') return else %Find at which image panel we drop it. - dist = zeros(1,length(DATA.Handles.imageaxes)); - for loop=1:length(DATA.Handles.imageaxes) + %dist = zeros(1,length(DATA.Handles.imageaxes)); + dist=zeros(1,length(DATA.ViewPanels)); + % for loop=1:length(DATA.Handles.imageaxes) + for loop=1:length(DATA.ViewPanels) p = get(DATA.Handles.imageaxes(loop),'position'); p = p(1:2)+0.5*p(3:4); %Center position dist(loop) = sqrt(sum(([x y]-p).^2)); %Euklidean distance - end; + end [~,ind] = min(dist); ind=ind(1); %just in case equal distance..! end end if ~isempty(ind) - %Store it - DATA.ViewPanels(ind) = no; - if (SET(no).ZSize==1) - DATA.ViewPanelsType{ind} = 'one'; - else - DATA.ViewPanelsType{ind} = DATA.GUISettings.ViewPanelsTypeDefault; - end - DATA.ViewIM{ind} = []; - DATA.Overlay(ind) = struct('alphadata', [], 'cdata', []); - DATA.CurrentPanel = ind; - - oldnos=SET(NO).Linked; - NO = no; - - % This is to ensure that linkaxes is removed when a non-linked stack is - % moved into a panel that was previously linked. /JU - panel=find(ismember(DATA.ViewPanels,NO)); - if ~isempty(panel)&&... - isappdata(DATA.Handles.imageaxes(panel(1)),'graphics_linkaxes')&&... - ~ismember(NO,oldnos); - %isempty(SET(NO).Flow) - linkaxes(DATA.Handles.imageaxes(panel),'off'); - end - drawfunctions('drawimageno',NO); - drawfunctions('drawallslices'); - DATA.switchtoimagestack(NO,true); %force - + viewfunctions('addno2panel',ind,no) end -%------------------------- -function addnotopanel(no) %#ok -%------------------------- -%Add image stack 'no' to panel - - global DATA NO SET - - ind=find(DATA.ViewPanels==0,1); - - if ~isempty(ind) - DATA.ViewPanels(ind) = no; - if (SET(no).ZSize==1) - DATA.ViewPanelsType{ind} = 'one'; - else - DATA.ViewPanelsType{ind} = DATA.GUISettings.ViewPanelsTypeDefault; - end - DATA.ViewIM{ind} = []; - DATA.Overlay(ind) = struct('alphadata', [], 'cdata', []); - DATA.CurrentPanel = ind; - - oldnos=SET(NO).Linked; - NO = no; - - % This is to ensure that linkaxes is removed when a non-linked stack is - % moved into a panel that was previously linked. /JU - panel=find(ismember(DATA.ViewPanels,NO)); - if ~isempty(panel)&&... - isappdata(DATA.Handles.imageaxes(panel(1)),'graphics_linkaxes')&&... - ~ismember(NO,oldnos); - %isempty(SET(NO).Flow) - linkaxes(DATA.Handles.imageaxes(panel),'off'); - end - drawfunctions('drawimageno',NO); - drawfunctions('drawallslices'); - DATA.switchtoimagestack(NO,true); %force - end - -%---------------------------- -function updateselectedslices -%---------------------------- -%Graphically updates which slices are selected. -global DATA SET NO - -for loop=1:prod(DATA.ViewMatrix) - no=DATA.ViewPanels(loop); - set(DATA.Handles.selectslicehandle{loop},'visible','off'); - switch DATA.ViewPanelsType{loop} - case {'montage','montagerow','montagefit'}%,'montagesegmented'} - if loop~=DATA.CurrentPanel - set(DATA.Handles.selectslicehandle{loop}(SET(no).StartSlice:SET(no).EndSlice),'linestyle','--')%'color',[0.7843 0.7843 0.5]); - else - set(DATA.Handles.selectslicehandle{loop}(SET(no).StartSlice:SET(no).EndSlice),'color',[1 1 0],'linestyle','-'); - end - set(DATA.Handles.selectslicehandle{loop}(SET(no).StartSlice:SET(no).EndSlice),'visible','on'); - case 'montagesegmented' - - %safety check so we dont go out of bounds when doing the montage LV -% ind=find(findfunctions('findslicewithendoall',no)+... -% findfunctions('findslicewithepiall',no)+... -% findfunctions('findslicewithrvendo',no)+... -% findfunctions('findslicewithrvepi',no)); - ind= getmontagesegmentedslices(no); - - if ind(1)>=SET(no).CurrentSlice || ind(end)<=SET(no).CurrentSlice - drawfunctions('drawimagepanel',loop) - end - -% if ~isempty(ind) -% if SET(no).StartSliceind(end)+1 -% SET(no).StartSlice=ind(end)+1; -% end -% -% if SET(no).EndSliceind(end)+1 -% SET(no).EndSlice=ind(end)+1; -% end -% -% if SET(no).EndSlice>SET(no).ZSize -% SET(no).EndSlice=SET(no).ZSize; -% end -% -% if SET(no).EndSlice==0 -% SET(no).EndSlice=1; -% end -% -% if SET(no).StartSlice>SET(no).ZSize -% SET(no).StartSlice=SET(no).ZSize; -% end -% -% if SET(no).StartSlice==0 -% SET(no).StartSlice=1; -% end -% -% SET(no).CurrentSlice = min([SET(no).CurrentSlice,SET(no).EndSlice]); -% SET(no).CurrentSlice = max([SET(no).CurrentSlice,SET(no).StartSlice]); -% end - - if loop~=DATA.CurrentPanel - set(DATA.Handles.selectslicehandle{loop}(SET(no).StartSlice:SET(no).EndSlice),'linestyle','--')%'color',[0.7843 0.7843 0.5]); - else - set(DATA.Handles.selectslicehandle{loop}(SET(no).StartSlice:SET(no).EndSlice),'color',[1 1 0],'linestyle','-'); - end - set(DATA.Handles.selectslicehandle{loop}(SET(no).StartSlice:SET(no).EndSlice),'visible','on'); - otherwise - %nothing for now. - end; -end; - -%fix so that linked images are connected -nos = SET(NO).Linked; - -panelstodo=find(ismember(DATA.ViewPanels,nos)); -nos=DATA.ViewPanels(panelstodo); -for loop=1:length(panelstodo) - panel=panelstodo(loop); - no=nos(loop); - set(DATA.Handles.selectslicehandle{panel},'visible','off'); - switch DATA.ViewPanelsType{panel} - case {'montage','montagerow','montagefit','montagesegmented'} - set(DATA.Handles.selectslicehandle{panel}(SET(no).StartSlice:SET(no).EndSlice),'visible','on'); - otherwise - %nothing for now. - end; -end; - %-------------------------- function z = remap(im,cmap,c,b) %#ok %-------------------------- @@ -1256,7 +753,7 @@ function addnotopanel(no) %#ok if nargin<2 cmap = SET(NO).Colormap; -end; +end if nargin<4 c=SET(NO).IntensityMapping.Contrast; b=SET(NO).IntensityMapping.Brightness; @@ -1285,123 +782,20 @@ function addnotopanel(no) %#ok end z = fastremap(im,single(map)); z = reshape(z,outsize); - end; -end; - -%------------------------------------ -function result = updateintersections_Callback(slices,no,type) %#ok -%------------------------------------ -% Calculates the intersection of a endocardial segmentation -% and SET(no) for -% slices == 'all' -% or -% slices == 'current' -% -% Allowed segmenation 'type' is 'LVEndo' or 'RVEndo' -% -% Calculates intersection for SET(NO) if nargin==1. -% Returns false if calculations fails - -% Marten Larsson, June, 2009 - -global DATA NO SET - -if nargin == 1 - no = NO; - type = 'LV Endocardial'; -end; - -result = true; -segno = []; - -switch type - case 'LV Endocardial' - % Find sets with LV endocardial segmentation - for i=1:length(SET) - if ~isempty(SET(i).EndoX) && any(any(any(~isnan(SET(i).EndoX)))) - segno = [segno i]; %#ok - end; - end; - case 'RV Endocardial' - % Find sets with RV endocardial segmentation - for i=1:length(SET) - if ~isempty(SET(i).RVEndoX) && any(any(any(~isnan(SET(i).RVEndoX)))) - segno = [segno i]; %#ok - end; - end; -end; - -if isempty(segno) - myfailed('No segmentation found',DATA.GUI.Segment); - result = false; - return; -end; - -if length(segno)>1 - segstring = cell(length(segno),1); - for i = 1: length(segno) - segstring{i} = sprintf('Image stack %d - %s',segno(i),SET(segno(i)).ImageType); - end; - - [selected, ok] = listdlg('ListString',segstring,... - 'SelectionMode','single',... - 'PromptString','Chose image stack to use:',... - 'ListSize',[300 100]); - - if ~ok - result = false; - return; - end; - segno = segno(selected); -end; - -calcsegintersect(segno,no,slices,type); - -drawfunctions('drawall'); - -%----------------------------------------------- -function [intersections, maxintersect] = getendointersection(no) %#ok -%----------------------------------------------- -% Returns the intersection of the endocardial segmentation and the current -% slice and current time frame of SET(no) - -global SET - -intersections = []; -maxintersect = []; - -slice = SET(no).CurrentSlice; -time = SET(no).CurrentTimeFrame; + end +end -if(isfield(SET,'Intersection') && ... - isstruct(SET(no).Intersection)) - - isectnum = strncmp('LV Endocardial',{SET(no).Intersection.Type},14); - - if ~isempty(isectnum) && ... - ~(isempty(SET(no).Intersection(isectnum).Slice(slice).TimeFrame)) - - intersections = SET(no).Intersection(isectnum)... - .Slice(slice).TimeFrame(time).Intersection; - maxintersect = SET(no).Intersection(isectnum).MaxIntersect; - end; - -end; -%------------------ -function updateflow -%------------------ -%calculate flow and graphically update -global DATA SET +%------------------------- +function updatemeasurement %#ok +%------------------------- +%calculate measurement and graphically update +global DATA -if ~isempty(DATA.FlowNO) - no = DATA.FlowNO; - if ~isempty(SET(no).Flow) && isfield(SET(no).Flow,'MagnitudeNo') && SET(no).RoiN > 0 - calcfunctions('calcflow',no); - end -end -DATA.updateaxestables('flow'); +DATA.updatemeasurementreport; +%updateplot +DATA.updatemeasurementaxes; %---------------------------------- function updatevolume(lvsegchanged) @@ -1414,38 +808,96 @@ function updatevolume(lvsegchanged) end rotstring = ''; -specstring = sprintf('\n'); +specstring = newline; %Error check if isempty(SET(NO).ImageViewPlane) SET(NO).ImageViewPlane = 'Unspecified'; -end; +end calcd = -1; if ismember(SET(NO).ImageViewPlane,{'2CH','3CH','4CH'}) + [calcd,usednos] = longaxistools('calcbiplanevolume'); - if all(isnan(SET(NO).LVV)) || ~ismember(NO,usednos) - calcd = 0; - end -end - %DATA.AxesTables.volume.updateName('INFO','',true); -if calcd > 0 - %DATA.AxesTables.volume.updateName('INFO',translation.dictionary(sprintf('Volume from %d LAX stacks',calcd)),true); +% if all(isnan(SET(NO).LVV)) || ~ismember(NO,usednos) +% calcd = 0; +% end + for no = DATA.LVNO calcfunctions('volume_helper',no); end -elseif calcd == -1 + + %if current stack is a new contribution to a lax volume calculation in + %DATA.LVNO + %we need to add it to that + if any(ismember(usednos,DATA.LVNO)) + LAX_group = findfunctions('findlaxset',1); + LAX_group = LAX_group(LAX_group~=0); + if ~isempty(LAX_group) + DATA.LVNO = LAX_group; + str = []; + for i = 1:length(LAX_group) + str = [str, num2str(LAX_group(i)),',']; + end + str(end) = []; + if isfield(DATA.Handles,'lvstackpushbutton') + set(DATA.Handles.lvstackpushbutton,'String',sprintf('Stack #%s',str)); + end + else + if isfield(DATA.Handles,'lvstackpushbutton') + set(DATA.Handles.lvstackpushbutton,'String',sprintf('Stack #%d',DATA.LVNO(1))); + end + end + end +end + +if calcd == -1 calcfunctions('calcvolume',NO); else calcfunctions('volume_helper',NO); end -if DATA.Silent - return; -end; +% if calcd > 0 +% for no = DATA.LVNO +% calcfunctions('volume_helper',no); +% end +% elseif calcd == -1 +% calcfunctions('calcvolume',NO); +% else +% calcfunctions('volume_helper',NO); +% end + +if DATA.Silent + return; +end + +%update all reports +DATA.updatelvreport +DATA.updatervreport +% DATA.updateflowreport -DATA.updateaxestables('measure'); -DATA.updateaxestables('volume'); +%updateplot +DATA.updatevolumeaxes +%DATA.updatetimebaraxes + + +% if strcmp(DATA.ProgramName,'Segment') +% %update all reports +% DATA.updatelvreport +% DATA.updatervreport +% %DATA.updatemeasurementreport +% +% %updateplot +% DATA.updatevolumeaxes +% elseif DATA.LVNO == NO || DATA.RVNO == NO +% %update all reports +% DATA.updatelvreport +% DATA.updatervreport +% %DATA.updatemeasurementreport +% +% %updateplot +% DATA.updatevolumeaxes +% end if lvsegchanged if ismember('Strain from tagging',{SET.ImageType}) @@ -1501,7 +953,7 @@ function updatevolume(lvsegchanged) else %set slice slice = SET(NO).CurrentSlice; -end; +end %-------------------------------- function no=getclickedpreview(~,y) @@ -1514,92 +966,7 @@ function updatevolume(lvsegchanged) end no = floor(y/DATA.GUISettings.ThumbnailSize)+1; - -%---------------------------- -function switchtoslice(slice) -%---------------------------- -%Called when current slice has changed. -%If slice has changed, make sure montage/one are in sync -%Does nothing if slice = CurrentSlice -global DATA SET NO - -if ~isequal(slice,SET(NO).CurrentSlice)||... - ~isequal(SET(NO).StartSlice,SET(NO).EndSlice) - %Update linked stacks as well - nos = SET(NO).Linked; - for no=unique(nos) - %copy to linked flows - SET(no).StartSlice=slice; - SET(no).CurrentSlice=slice; - SET(no).EndSlice=slice; - if ismember(no,DATA.ViewPanels) - updateoneim(no); - centeronslice(slice,no,SET(no).ZSize); - drawfunctions('drawsliceno',no); - end - end - drawfunctions('drawintersections'); - updateselectedslices; -end - -%---------------------------------------------------- -function switchtolongaxisslice(slice,laxfield,silent) -%---------------------------------------------------- -%Called when slice has changed in HLA or VLA view -global SET NO - -if nargin < 3 - silent = false; -end -if slice ~= SET(NO).(laxfield).slice - %Update linked stacks as well - nos = SET(NO).Linked; - for no=unique(nos) - %copy to linked flows - SET(no).(laxfield).slice=slice; - if ~silent - updateoneim(no); - end - end -end - -if silent - return -end -centeronslice(slice,NO,SET(NO).ZSize); -drawfunctions('drawsliceno',NO); -drawfunctions('drawintersections'); -updateselectedslices; -%----------------------------------- -function centeronslice(slice,no,zsz) -%----------------------------------- -%Put slice in center of montagefit view -global DATA -for panel = find(DATA.ViewPanels == no) - - if strcmp(DATA.ViewPanelsType{panel},'montagefit') - viewimsz = size(DATA.ViewIM{panel}); - if viewimsz(1) < viewimsz(2) - limname = 'XLim'; - limmax = viewimsz(2); - else - limname = 'YLim'; - limmax = viewimsz(1); - end - slicewidth = limmax/zsz; - slicemid = slicewidth*(slice-1)+slicewidth/2; - lims = get(DATA.Handles.imageaxes(panel),limname); - newlims = slicemid + [-0.5 0.5]*diff(lims); - set(DATA.Handles.imageaxes(panel),limname,newlims); - %updatemodeldisplay(no); - end -end - -%----------------------------- -function updatemodeldisplay(~) -%----------------------------- -%Do nothing, introduced to disable excessive calls to updatemodeldisplay %-------------------- function r = getfieldifcommon(SET, fname) %#ok @@ -1618,198 +985,6 @@ function updatemodeldisplay(~) end end -%-------------------------------- -function updateoneim(no) -%-------------------------------- -%Updates viewim for 'one view' or 'mmodespatial' -%Called when changed currentslice -global DATA SET - -nos = SET(no).Linked; - -%Call make view im if necessary -%This is time consuming, though the alternative will consume memory -for loop=1:length(DATA.ViewPanels) -% if ... - if (ismember(DATA.ViewPanels(loop),nos))&&... - ismember(DATA.ViewPanelsType{loop},{'one','mmodespatial','ortho','hla','vla','gla'}) - makeviewim(loop,DATA.ViewPanels(loop)); - end; - -end; - -if ismember('mmodetemporal',DATA.ViewPanelsType) - updatemmode; -end - -%-------------------------------- -function movealltowardsbase_Callback -%-------------------------------- -% Changes CurrentSlice (and that of parallel image stacks) -% towards base - -% Marten Larsson, June, 3, 2009 - -global SET NO - -% Move SET(NO) towards base -if SET(NO).CurrentSlice>1 - slice = SET(NO).CurrentSlice-1; - SET(NO).CurrentSlice = slice; - SET(NO).StartSlice = slice; - SET(NO).EndSlice = slice; - - updateoneim(NO); - drawfunctions('drawsliceno',NO); -end; - -updateparallelsets; - -if length(SET(NO).Linked) > 1 - nos = SET(NO).Linked; - - for no=nos - SET(no).CurrentSlice = SET(NO).CurrentSlice; - SET(no).StartSlice = SET(NO).CurrentSlice; - SET(no).EndSlice = SET(NO).CurrentSlice; - end -end - -drawfunctions('drawintersections'); -updateselectedslices; - -%-------------------------------- -function movealltowardsapex_Callback -%-------------------------------- -% Changes CurrentSlice (and that of parallel image stacks) -% towards apex - -% Marten Larsson, June, 3, 2009 - -global SET NO - -% ind=find(findfunctions('findslicewithendoall',NO)+... -% findfunctions('findslicewithepiall',NO)+... -% findfunctions('findslicewithrvendo',NO)+... -% findfunctions('findslicewithrvepi',NO)); -% -% Move SET(NO) towards base -if SET(NO).CurrentSlice < SET(NO).ZSize - slice = SET(NO).CurrentSlice+1; - SET(NO).CurrentSlice = slice; - SET(NO).StartSlice = slice; - SET(NO).EndSlice = slice; - - updateoneim(NO); - drawfunctions('drawsliceno',NO); -end; - -updateparallelsets; - -if length(SET(NO).Linked) > 1 - nos = SET(NO).Linked; - - for no=nos - SET(no).CurrentSlice = SET(NO).CurrentSlice; - SET(no).StartSlice = SET(NO).CurrentSlice; - SET(no).EndSlice = SET(NO).CurrentSlice; - end -end - -drawfunctions('drawintersections'); -updateselectedslices; - -%-------------------------- -function updateparallelsets -%-------------------------- -% Chages CurrentSlice in SETs that are parallel to SET(NO) to the slice -% closest to SET(NO).CurrentSlice -% -% Help function to movealltowardsbase_Callback and -% movealltowardsapex_Callback - -% Marten Larsson, June, 3, 2009 - -global DATA SET NO - -% Get open SETs panels but exclude NO -openpanels = DATA.ViewPanels; -openpanels = unique(openpanels); -openpanels = openpanels(openpanels~=NO&openpanels~=0); - -% Find SETs that are parallel to SET(NO), but not a linked flow. -if ~isempty(SET(NO).Flow) - flownos = [... - SET(NO).Flow.MagnitudeNo ... - SET(NO).Flow.PhaseNo ... - SET(NO).Flow.PhaseX ... - SET(NO).Flow.PhaseY ... - SET(NO).Flow.Angio ... - SET(NO).Flow.VelMag]; -else - flownos = []; -end -parallel = []; -for i = openpanels - sameview = orientationcomparison(NO,i); - linkedflow = any(flownos == i); % SET(i) is linked to SET(NO) via SET(NO).Flow. - % This case is handled by updateoneim(). - if sameview && ~linkedflow - parallel = [parallel i]; %#ok - end; -end; - -if not(isempty(parallel)) - % Calculate new CurrentSlide for parallel SETs - viewdir = cross(SET(NO).ImageOrientation(1:3),SET(NO).ImageOrientation(4:6))'; - currzdist = (SET(NO).CurrentSlice-1)*(SET(NO).SliceThickness+SET(NO).SliceGap); - - % DEBUG - % disp(sprintf('SET(NO).CurrentSlice z-distance: %d mm', currzdist)); - - oldNO = NO; - oldlink=SET(NO).Linked; - domontageupdate=0; - for i = 1:length(parallel) - % Calculate closest slice in parallel SETs and change their - % CurrentSlice - slicethickness = SET(parallel(i)).SliceThickness + SET(parallel(i)).SliceGap; - zdistances = 0:slicethickness:(slicethickness * (SET(parallel(i)).ZSize-1)); - zdiff = SET(parallel(i)).ImagePosition - SET(NO).ImagePosition; - zdiff = dot(zdiff,viewdir); - zdistances = zdistances - zdiff; - [~,slice] = min(abs(zdistances - currzdist)); - SET(parallel(i)).CurrentSlice = slice; - SET(parallel(i)).StartSlice = slice; - SET(parallel(i)).EndSlice = slice; - - % DEBUG - %disp(sprintf('SET(%d).CurrentSlice z-distance: %d mm', parallel(i), round(zdistances(slice)))); - - % Update images - - if any(strcmp({DATA.ViewPanelsType{DATA.ViewPanels==parallel(i)}},'montage')) -% updateselectedslices; - %Trick it claiming that the images are linked for a short wile - SET(NO).Linked=[SET(NO).Linked parallel(i)]; - domontageupdate=1; - end - - if any(~strcmp({DATA.ViewPanelsType{DATA.ViewPanels==parallel(i)}},'montage')) - updateoneim(parallel(i)); % this fcn changes NO !!! - drawfunctions('drawsliceno',parallel(i)); - end - - %drawfunctions('drawsliceno',parallel(i)); - NO = oldNO; - end; - if domontageupdate - updateselectedslices - end - SET(NO).Linked=oldlink; - -end; - %---------------------------------------------------- function sameview = orientationcomparison(setindex1,setindex2) %---------------------------------------------------- @@ -1831,7 +1006,7 @@ function updateoneim(no) else sameview = false; return; -end; +end %---------------------------------------- function smoothendowall_Callback(no) @@ -1841,11 +1016,20 @@ function smoothendowall_Callback(no) %Einar Heiberg -global SET NO +global SET NO DATA if nargin<1 no = NO; -end; +end +tools('connectinterpolation',no,{'EndoInterp','EpiInterp'}); +%We need to have both endo and epi to do this +endotfs = findfunctions('findframeswithsegmentation','Endo',no,SET(no).CurrentSlice); +epitfs = findfunctions('findframeswithsegmentation','Epi',no,SET(no).CurrentSlice); + +if ~(endotfs(SET(no).CurrentTimeFrame) && epitfs(SET(no).CurrentTimeFrame)) + myfailed('Need both Endo and Epi segmentation to even out wall') + return +end tools('enableundo'); @@ -1889,476 +1073,31 @@ function smoothendowall_Callback(no) %Update graphically %Update -segment('updatemodeldisplay'); segment('updatevolume'); -drawfunctions('updatenopanels',no); - -%-------------------------------- -function movetowardsbase_Callback -%-------------------------------- -%Change current slice towards base -global DATA SET NO - -laxfield = upper(DATA.ViewPanelsType{DATA.CurrentPanel}); -if ismember(laxfield,{'HLA','VLA'}) - if SET(NO).(laxfield).slice>1 - switchtolongaxisslice(SET(NO).(laxfield).slice-1,laxfield); - end -elseif strcmp(laxfield,'GLA') - if SET(NO).HLA.slice>1 - silent = true; - if SET(NO).VLA.slice<=1 - silent = false; - end - switchtolongaxisslice(SET(NO).HLA.slice-round(cos(SET(NO).GLA.angle)),'HLA',silent); - end - if SET(NO).VLA.slice>1 - switchtolongaxisslice(SET(NO).VLA.slice+round(sin(SET(NO).GLA.angle)),'VLA'); - end -else - if SET(NO).CurrentSlice>1 - switchtoslice(SET(NO).CurrentSlice-1); - end; -end - -%-------------------------------- -function movetowardsapex_Callback -%-------------------------------- -%Change current slice towards apex -global DATA SET NO - -laxfield = upper(DATA.ViewPanelsType{DATA.CurrentPanel}); -if ismember(laxfield,{'HLA','VLA'}) - if SET(NO).(laxfield).slice=SET(NO).VLA.maxslice - silent = false; - end - switchtolongaxisslice(SET(NO).HLA.slice+round(cos(SET(NO).GLA.angle)),'HLA',silent); - end - if SET(NO).VLA.slice -%---------------------------------- -%play all displayed image stacks - -global DATA -DATA.Run = 0; - -stateandicon=iconson('play'); - -icon=stateandicon{2}; - -if icon.isindented==0 - stopmovie_Callback; - return; -else - playall_Helper -end - - -%---------------------------------- -function playall_Helper -%---------------------------------- -%Starts movie display of all visible image stacks. -global DATA SET NO - -DATA.Run = 1; %Start the movie :-) - -%find what NO's to use -nos = unique(DATA.ViewPanels(:)); -nos = nos(nos>0); %Remove zeros -maxt = 0; -for loop=nos' - if SET(loop).TSize>maxt - maxt = SET(loop).TSize; - end; -end; - -DATA.StartFrame = SET(NO).CurrentTimeFrame;%DATA.StartFrame = 1; -DATA.StartTime = now; - -%Run this loop until stopped by setting DATA.Run==0 -t = 1; - -if DATA.Record - DATA.Record = false; %otherwise nextframe will also store... - for loop=1:SET(NO).TSize - nextallframe_Callback; - DATA.MovieFrame = mygetframe(DATA.imagefig); - export('exportmovierecorder_Callback','newframe'); - - end; - return; -end; - -%If not record then try to run according to beattime. -if ~DATA.Record - while true - ind = find(cat(1,SET(:).TSize)>1); - if isempty(ind) - ind = 1; - else - ind = ind(1); %Take first - end; - beattime = SET(ind).BeatTime; - - %Not recording just play along as fast as possible - nos = unique(DATA.ViewPanels(DATA.ViewPanels > 0)); - for no=nos([SET(nos).TSize] > 1) - t = 1+mod(floor(rem(now-DATA.StartTime,1)*24*3600/(beattime/maxt)+DATA.StartFrame),maxt); - %SET(no).CurrentTimeFrame = max(min(round(SET(no).TSize*(t/maxt)),SET(no).TSize),1); - - for linkno = SET(no).Linked - SET(linkno).CurrentTimeFrame = max(min(round(SET(no).TSize*(t/maxt)),SET(no).TSize),1); - end - - drawfunctions('updatenopanels',no); - %Some error checking - if isempty(DATA) - return; %Someone has exited. - end; - - if DATA.Run==0 - %Ensure all on the same timeframe - for loop=1:length(SET) - SET(loop).CurrentTimeFrame = max(min(round(SET(loop).TSize*(t/maxt)),SET(loop).TSize),1); - end; - return; - end; - - end; %Loop over panels - drawnow% - pause(0.01) - - end; %not recording clause - -end; - -%------------------------------------ -function playmovie_Callback(keypress) %#ok -%------------------------------------ -%Starts playing current image stack as a movie. -global DATA SET NO - -% if nargin > 0 -% if isequal(get(DATA.Handles.playmovieicon,'enable'),'off') -% return -% end -% if isequal(get(DATA.Handles.playmovieicon,'state'),'off') -% set(DATA.Handles.playmovieicon,'state','on'); -% elseif isequal(get(DATA.Handles.playmovieicon,'state'),'on') -% set(DATA.Handles.playmovieicon,'state','off'); -% else %if handle is empty, icon is unavailable -% playall_Callback('keypressed'); -% return -% end -% end - -% %Opposide since it toggles when pressed -% if isequal(get(DATA.Handles.playmovieicon,'state'),'off') -% stopmovie_Callback; -% return; -% end; - -%Check if play all is running. -% if isequal(get(DATA.Handles.playallicon,'state'),'on') -% stopmovie_Callback; -% return; -% end; - -if DATA.Run==1 - stopmovie_Callback; - return; -end - -%figure(DATA.imagefig); -DATA.Run = 1; %Start the movie :-) -%set(DATA.Handles.playmovieicon,'state','on'); -DATA.StartFrame = SET(NO).CurrentTimeFrame; -DATA.StartTime = now; - -%Run this loop until stopped by setting DATA.Run==0 -while true - if isempty(DATA) - return; %Someone has exited. - end; - drawfunctions('drawsliceno'); - drawnow; %Not expose since want to be able to do callbacks - if DATA.Record - drawnow; - DATA.MovieFrame = mygetframe(DATA.imagefig); - export('exportmovierecorder_Callback','newframe'); - end; - if DATA.Run==0 - return; - end; - %Do pause to release CPU burden. - pause(0.5*SET(NO).BeatTime/SET(NO).TSize); -end; +drawfunctions('drawno',no) %-------------------------- function stopmovie_Callback %-------------------------- %End movie display. global DATA -DATA.Run = 0; -stateandicon=segment('iconson','play'); -stateandicon{2}.undent; -DATA.Handles.permanenticonholder.render; - -%--------------------------------------- -function viewhideall_Callback(varargin) %#ok -%--------------------------------------- -%all hide buttons -global DATA -stateandicon=iconson('hideall'); -state=stateandicon{1}; -hidecell={'hideplus','hidemar','hidescar',... 'hidepins', - 'hideintersections','hideothercontour','hideinterp','hidelv','hiderv','hideroi','hidemeasure','hidepoint','hidetext'};%,'colorbar'}; -stateandicon = iconson(hidecell); -availableicons = find(cellfun(@(x) isa(x,'myicon'),stateandicon(:,2)))'; -if state - for i=availableicons - icon = stateandicon{i,2}; - icon.cdataDisplay=icon.cdataIndent; - icon.isindented=1; - end - % for name=hidecell -% stateandicon=iconson(name); -% icon=stateandicon{1,2}; -% icon.cdataDisplay=icon.cdataIndent; -% icon.isindented=1; -% end -else - for i=availableicons - icon = stateandicon{i,2}; - icon.cdataDisplay=icon.cdata; - icon.isindented=0; - end - % for name=hidecell -% stateandicon=iconson(name); -% icon=stateandicon{1,2}; -% icon.cdataDisplay=icon.cdata; -% icon.isindented=0; -% end -end -drawfunctions('updatevisibility'); -DATA.Handles.configiconholder.render; - -%------------------------------- -function hide(names,states) -%-------------------------- -%Gets and sets icons with specific name in the different iconholders even those not showing at the moment according to state -global DATA -stateandicon = segment('iconson',names); +DATA.Run = 0; -for i =1:size(stateandicon,1) - stateandicon{i,2}.isindented=states(i); +try + stateandicon=viewfunctions('iconson','play'); + stateandicon{2}.undent; + DATA.Handles.permanenticonholder.render; +catch end -DATA.Handles.configiconholder.render; -drawfunctions('updatevisibility'); - -%------------------------- -function allhidden -%---------------------- -%show/hide all overlayes in the image view - -global DATA -stateandicon=iconson('hideall'); -hideallstate=stateandicon{1}; -hideallicon=stateandicon{2}; - -if hideallstate -hidecell={'hideplus','hidemar','hidescar',...'hidepins', - 'hideintersections','hideothercontour','hideinterp','hidelv','hiderv','hideroi','hidemeasure','hidepoint','hidetext'};%,'colorbar'}; - stateandicon = iconson(hidecell); - availableicons = cellfun(@(x) isa(x,'myicon'),stateandicon(:,2)); - state=[stateandicon{availableicons,1}]; -% for name=hidecell -% stateandicon=iconson(name); -% state=[state;stateandicon{1}]; -% end - if any(state==0) - hideallicon.undent - DATA.Handles.permanenticonholder.render; - end -end +%---------------------------------- +function viewspecial_Callback(mode) %#ok +%---------------------------------- +%Called to switch to predefined layouts of the GUI. Mode is current mode to +%use. -%--------------------------------------- -function viewhideplus_Callback(varargin) %#ok -%--------------------------------------- -%Toggle visibility of center + -drawfunctions('updatevisibility'); -allhidden - -%--------------------------------------- -function viewhidepins_Callback(varargin) %#ok -%--------------------------------------- -%Toggle visibility of pins -drawfunctions('updatevisibility'); -allhidden -%------------------------------------------------ -function viewhideintersections_Callback(varargin) %#ok -%------------------------------------------------ -%Toggle visibility of plane intersections -drawfunctions('updatevisibility'); -allhidden -%----------------------------------------------- -function viewhideothercontour_Callback(varargin) %#ok -%----------------------------------------------- -%Toggle visibility of contours from other image stacks -drawfunctions('updatevisibility'); -allhidden -%----------------------------------------------- -function viewhideinterp_Callback(varargin) %#ok -%----------------------------------------------- -%Toggle visibility of contours from other image stacks -drawfunctions('updatevisibility'); -allhidden -%-------------------------------------- -function viewhidelv_Callback(varargin) %#ok -%-------------------------------------- -%Toggle visibility of lv segmentation -drawfunctions('updatevisibility'); -allhidden -%-------------------------------------- -function viewhiderv_Callback(varargin) %#ok -%-------------------------------------- -%Toggle visibility of rv segmentation -drawfunctions('updatevisibility'); -allhidden -%-------------------------------------- -function viewhideroi_Callback(varargin) %#ok -%-------------------------------------- -%Toggle visibility of roi's -drawfunctions('updatevisibility'); -allhidden -%-------------------------------------- -function viewhidescar_Callback(varargin) %#ok -%-------------------------------------- -%Toggle visibility of scar contours -%global DATA -drawfunctions('updatevisibility'); -%drawfunctions('drawall',DATA.ViewMatrix); -allhidden -%-------------------------------------- -function viewhidescarextent_Callback(varargin) %#ok -%-------------------------------------- -%Toggle visibility of auto scar extent contours -%global DATA -drawfunctions('updatevisibility'); -%drawfunctions('drawall',DATA.ViewMatrix); -allhidden -%-------------------------------------- -function viewhidemar_Callback(varargin) %#ok -%-------------------------------------- -%Toggle visibility of MaR contours -%global DATA -%drawfunctions('drawall',DATA.ViewMatrix); -drawfunctions('updatevisibility'); -allhidden -%--------------------------------- -function viewhidemeasures_Callback %#ok -%--------------------------------- -%Toggle visibility of measurements -drawfunctions('updatevisibility'); -allhidden -%--------------------------------- -function viewhidepoints_Callback %#ok -%--------------------------------- -%Toggle visibility of annotation points -drawfunctions('updatevisibility'); -allhidden -%--------------------------------------- -function viewhidetext_Callback(varargin) %#ok -%--------------------------------------- -%Toggle visibility of text -drawfunctions('updatevisibility'); -allhidden -%--------------------------------- -function viewhidecolorbar_Callback %#ok -%--------------------------------- -%Toggle visibility of colorbar -global DATA - -stateandicon=iconson('colorbar'); -state=stateandicon{1}; -%stateandicon{2}.isindented=state; -if ~state - DATA.GUISettings.ShowColorbar = false; -else - DATA.GUISettings.ShowColorbar = true; -end -drawfunctions('drawall',DATA.ViewMatrix); -allhidden -%----------------------------------- -function viewhidepap_Callback %#ok -%--------------------------------- -%Toggle visibility of papillary overlay -global DATA NO - -makeviewim(DATA.CurrentPanel,NO); -drawfunctions('drawall',DATA.ViewMatrix); -allhidden -%-------------------------- -function viewhidemanualinteraction_Callback %#ok -%-------------------------- -%toogle visibility of manual interaction of Scar/MaR -global DATA - -drawfunctions('drawall',DATA.ViewMatrix); -allhidden -%------------------------------- -function viewaddtoolbar_Callback %#ok -%------------------------------- -%Helper function to add a toolbar. -global DATA -h = get(0,'children'); -set(h,'menubar','figure'); -set(DATA.imagefig,'menubar','none'); - -%-------------------------------- -function viewinterp_Callback(val) %#ok -%-------------------------------- -%Update if the view interpolated view is selected / unselected - -global DATA -if nargin < 1 - val = ~DATA.Pref.ViewInterpolated; -end -DATA.Pref.ViewInterpolated = val; -% if val -% set(DATA.Handles.viewpixelsmenu,'Checked','off'); -% % set(DATA.Handles.viewpixelyicon,'state','off'); -% else -% set(DATA.Handles.viewpixelsmenu,'Checked','on'); -% % set(DATA.Handles.viewpixelyicon,'state','on'); -% end -DATA.ViewIM = cell(size(DATA.ViewIM)); -drawfunctions('drawall'); - -%---------------------------------- -function viewspecial_Callback(mode) %#ok -%---------------------------------- -%Called to switch to predefined layouts of the GUI. Mode is current mode to -%use. - -global DATA SET NO +global DATA SET NO switch mode case 'cine' @@ -2366,106 +1105,66 @@ function viewspecial_Callback(mode) %#ok %allcineno = findfunctions('findno'); shall be changed to show all cine if isempty(cineno) cineno = 1; - end; - DATA.ViewMatrix = [1 1]; - DATA.ViewPanels = cineno; - DATA.ViewPanelsType = {'montage'}; - [rows,cols] = calcfunctions('calcrowscols',cineno,SET(cineno).ZSize); - DATA.ViewPanelsMatrix = {[rows cols]}; - DATA.ViewIM = {[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); - DATA.CurrentPanel = 1; - NO=cineno; - drawfunctions('drawall',DATA.ViewMatrix); + end + myworkon; + viewfunctions('setview',1,1,cineno,{'montage'}); + myworkoff; case 'lv' - cineno = DATA.LVNO(1); + if ~isempty(DATA.LVNO) + cineno = DATA.LVNO(1); + else + lvrvstacks = findfunctions('findcineshortaxisno',true); + if not(isempty(lvrvstacks)), cineno = lvrvstacks(1); else cineno = []; end + if not(isempty(cineno)) + DATA.LVNO = cineno; + end + end if ~isempty(cineno) - DATA.ViewMatrix = [1 1]; - DATA.ViewPanels = cineno; - DATA.ViewPanelsType = {'montage'}; - [rows,cols] = calcfunctions('calcrowscols',cineno,SET(cineno).ZSize); - DATA.ViewPanelsMatrix = {[rows cols]}; - DATA.ViewIM = {[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); - DATA.CurrentPanel = 1; - NO=cineno; - drawfunctions('drawall',DATA.ViewMatrix); - + myworkon; + viewfunctions('setview',1,1,cineno,{'montage'}); + myworkoff; else myfailed('No LV stack found.',DATA.GUI.Segment); return; end - case 'rv' - cineno = DATA.RVNO; + case 'rv' + if ~isempty(DATA.RVNO) + cineno = DATA.RVNO(1); + else + lvrvstacks = findfunctions('findcineshortaxisno',true); + if not(isempty(lvrvstacks)), cineno = lvrvstacks(2); else cineno = []; end + if not(isempty(cineno)) + DATA.RVNO = cineno; + end + end if ~isempty(cineno) - DATA.ViewMatrix = [1 1]; - DATA.ViewPanels = cineno; - DATA.ViewPanelsType = {'montage'}; - [rows,cols] = calcfunctions('calcrowscols',cineno,SET(cineno).ZSize); - DATA.ViewPanelsMatrix = {[rows cols]}; - DATA.ViewIM = {[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); - DATA.CurrentPanel = 1; - NO=cineno; - drawfunctions('drawall',DATA.ViewMatrix); - drawfunctions('drawthumbnails') + myworkon; + viewfunctions('setview',1,1,cineno,{'montage'}); + myworkoff; else myfailed('No RV stack found.',DATA.GUI.Segment); return; end case 'cinescar' - cineno = DATA.LVNO(1); - if isempty(cineno) - cineno = findfunctions('findcineshortaxisno'); + if isempty(DATA.LVNO) + cineno = findfunctions('findcineshortaxisno',false, 28); + else + cineno = DATA.LVNO(1); end scarno = findfunctions('findscarshortaxisno'); if isempty(scarno) - myfailed('No scar stack found.',DATA.GUI.Segment); + myfailed('No scar stack found.',DATA.GUI.Segment); return; - end; + end + myworkon; if ~isempty(cineno) && ~isempty(scarno) % plot both scar and cine image - DATA.ViewMatrix = [2 1]; - DATA.ViewPanels = [cineno(1) scarno(1)]; - DATA.ViewPanelsType = {'montagerow','montagerow'}; - for panel = 1:2 - no = DATA.ViewPanels(panel); - if SET(no).ZSize>8 - DATA.ViewPanelsMatrix{panel}(1) = 2; - DATA.ViewPanelsMatrix{panel}(2) = ceil(SET(no).ZSize/2); - else - DATA.ViewPanelsMatrix{panel}(1) = 1; - DATA.ViewPanelsMatrix{panel}(2) = SET(no).ZSize; - end; - end - DATA.ViewIM = {[],[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); - DATA.Overlay(2) = struct('alphadata',[],'cdata',[]); + viewfunctions('setview',2,1,[cineno,scarno],{'montagerow','montagerow'},[scarno 2]); else % only plot scar image - DATA.ViewMatrix = 1; - DATA.ViewPanels = scarno(1); - DATA.ViewPanelsType = {'montagerow'}; - for panel = 1 - no = DATA.ViewPanels(panel); - if SET(no).ZSize>8 - DATA.ViewPanelsMatrix{panel}(1) = 2; - DATA.ViewPanelsMatrix{panel}(2) = ceil(SET(no).ZSize/2); - else - DATA.ViewPanelsMatrix{panel}(1) = 1; - DATA.ViewPanelsMatrix{panel}(2) = SET(no).ZSize; - end; - end - DATA.ViewIM = {[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); + viewfunctions('setview',1,1,[scarno],{'montage'}); end - for i = 1:numel(DATA.ViewPanels) - if DATA.ViewPanels(i) == scarno(1) - DATA.CurrentPanel = i; - end - end - NO=DATA.ViewPanels(DATA.CurrentPanel); - drawfunctions('drawall',DATA.ViewMatrix); + myworkoff; case 'flow' flowno = DATA.FlowNO; if isempty(flowno) @@ -2474,81 +1173,111 @@ function viewspecial_Callback(mode) %#ok if isempty(flowno) myfailed('No flow stacks found.',DATA.GUI.Segment); return; - end; - haveflow = zeros(length(flowno),1); for flownoloop = 1:length(flowno), haveflow(flownoloop) = not(isempty(SET(flowno(flownoloop)).Flow)); end + end + haveflow = zeros(length(flowno),1); + for flownoloop = 1:length(flowno) + haveflow(flownoloop) = not(isempty(SET(flowno(flownoloop)).Flow)); + end if sum(haveflow) == 0 myfailed('No flow stacks found.',DATA.GUI.Segment); - return; - end; + return; + end flowno = flowno(haveflow==1); - no = flowno(1); %For now take first, maybe late do a toggle... + no = flowno(1); %For now take first, maybe late do a toggle... +% DATA.FlowNO = no; %set also flowno to be found nom = SET(no).Flow.MagnitudeNo; nop = SET(no).Flow.PhaseNo; if isempty(nop) myfailed('Flow view only works for flow image stacks with trough-plane flow.',DATA.GUI.Segment); return; - end; - DATA.ViewMatrix = [1 2]; - DATA.ViewPanels = [nom nop]; - DATA.ViewPanelsType = {'one','one'}; - DATA.ViewIM = {[],[]}; - DATA.Overlay = struct('alphadata',[],'cdata',[]); - DATA.Overlay(2) = struct('alphadata',[],'cdata',[]); - DATA.CurrentPanel = 1; - NO=no; - drawfunctions('drawall',DATA.ViewMatrix); - switchtopanel(1); + end + myworkon; + viewfunctions('setview',1,2,[nom,nop],{'one','one'}); + myworkoff; case 'perfusion' stressno = findfunctions('findstack','Perfusion Stress'); restno = findfunctions('findstack','Perfusion Rest'); if isempty(stressno) && isempty(restno) myfailed('No perfusion stacks found.',DATA.GUI.Segment); return; - end; + end + myworkon; if isempty(stressno) - DATA.ViewMatrix = [1 1]; - DATA.ViewPanels = restno; - DATA.ViewPanelsType = {'montagerow'}; - for panel = 1 - no = DATA.ViewPanels(panel); - DATA.ViewPanelsMatrix{panel}(1) = 1; - DATA.ViewPanelsMatrix{panel}(2) = SET(no).ZSize; - end - DATA.ViewIM = {[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); + viewfunctions('setview',1,1,restno,{'montagerow'}); elseif isempty(restno) - DATA.ViewMatrix = [1 1]; - DATA.ViewPanels = stressno; - DATA.ViewPanelsType = {'montagerow'}; - for panel = 1 - no = DATA.ViewPanels(panel); - DATA.ViewPanelsMatrix{panel}(1) = 1; - DATA.ViewPanelsMatrix{panel}(2) = SET(no).ZSize; - end - DATA.ViewIM = {[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); + viewfunctions('setview',1,1,restno,{'montagerow'}); else - DATA.ViewMatrix = [2 1]; - DATA.ViewPanels = [stressno restno]; - DATA.ViewPanelsType = {'montagerow','montagerow'}; - for panel = 1 - no = DATA.ViewPanels(panel); - DATA.ViewPanelsMatrix{panel}(1) = 1; - DATA.ViewPanelsMatrix{panel}(2) = SET(no).ZSize; - end - DATA.ViewIM = {[],[]}; %Clear viewim, force to recalc - DATA.Overlay = struct('alphadata',[],'cdata',[]); - DATA.Overlay(2) = struct('alphadata',[],'cdata',[]); + viewfunctions('setview',2,1,[stressno,restno],{'montagerow','montagerow'}); end - NO=DATA.ViewPanels(DATA.CurrentPanel); - drawfunctions('drawall',DATA.ViewMatrix); - + myworkoff; + case 'strainsax' + ftno = strcmp('Feature tracking',{SET.ImageType}); + saxno = strcmp('Short-axis',{SET.ImageViewPlane}); + [points,strainnos] = sort(ftno+saxno,'descend'); + strainno = strainnos(1); + if points(1)<1 || isempty(strainno) + myfailed('No strain stack found',DATA.GUI.Segment); + return; + end + myworkon; + viewfunctions('setview',1,1,strainno,{'montagerow'}); + myworkoff; + case 'strainlax' + twochno = strcmp('2CH',{SET.ImageViewPlane}); + threechno = strcmp('3CH',{SET.ImageViewPlane}); + fourchno = strcmp('4CH',{SET.ImageViewPlane}); + for noloop = 1:length(SET) + havestrain(noloop) = not(isempty(SET(noloop).StrainTagging)); + end + [points,strain2chnos] = sort(twochno+havestrain,'descend'); + [points,strain3chnos] = sort(threechno+havestrain,'descend'); + [points,strain4chnos] = sort(fourchno+havestrain,'descend'); + strain2chno = strain2chnos(1); + strain3chno = strain3chnos(1); + strain4chno = strain4chnos(1); + if isempty(strain2chno) && isempty(strain3chno) && isempty(strain4chno) + myfailed('No strain stack found',DATA.GUI.Segment); + return; + end + myworkon; + if not(isempty(strain2chno)) && not(isempty(strain3chno)) && not(isempty(strain4chno)) + viewfunctions('setview',1,3,[strain2chno,strain3chno,strain4chno],{'one','one','one'}); + elseif not(isempty(strain2chno)) && not(isempty(strain3chno)) + viewfunctions('setview',1,2,[strain2chno,strain3chno],{'one','one'}); + elseif not(isempty(strain2chno)) && not(isempty(strain4chno)) + viewfunctions('setview',1,2,[strain2chno,strain4chno],{'one','one'}); + elseif not(isempty(strain3chno)) && not(isempty(strain4chno)) + viewfunctions('setview',1,2,[strain3chno,strain4chno],{'one','one'}); + elseif not(isempty(strain2chno)) + viewfunctions('setview',1,1,strain2chno,{'montagerow'}); + elseif not(isempty(strain3chno)) + viewfunctions('setview',1,1,strain3chno,{'montagerow'}); + elseif not(isempty(strain4chno)) + viewfunctions('setview',1,1,strain4chno,{'montagerow'}); + end + myworkoff; case 'cinescarperf' case 'stress' otherwise myfailed('Unknown option to viewspecial_Callback',DATA.GUI.Segment); return; -end; +end +%adjust visible thumbnails so that NO is visible +nosafter = intersect(NO:NO+DATA.Pref.NumberVisibleThumbnails-1,1:length(SET)); +nosbefore = intersect(NO-DATA.Pref.NumberVisibleThumbnails+1:NO,1:length(SET)); +newnos = union(nosbefore,nosafter); +if length(SET) > DATA.Pref.NumberVisibleThumbnails + newnos = newnos(1:DATA.Pref.NumberVisibleThumbnails); + if min(DATA.VisibleThumbnails)-NO > 0 + whattodo = 'up'; + else + whattodo = 'down'; + end + DATA.VisibleThumbnails = newnos; + thumbnailslider_Callback(whattodo); +end +segment('updatemeasurement'); +DATA.updatetimebaraxes %------------------------ function zoomhelper(ax,f,no,panel) @@ -2567,13 +1296,14 @@ function zoomhelper(ax,f,no,panel) if nargin<2 myfailed('Expected two input arguments.',DATA.GUI.Segment); return; -end; +end if f < 1 && strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},'montagesegmented') mfzs = SET(NO).MontageFitZoomState; if mfzs(2)-mfzs(1)>=size(DATA.ViewIM{1},1) && ... mfzs(4)-mfzs(3)>=size(DATA.ViewIM{1},2) - viewimage_Callback('montage'); + %viewimage_Callback('montage'); + viewfunctions('setviewtype','montage'); return end end @@ -2680,11 +1410,11 @@ function zoomhelper(ax,f,no,panel) else panelstodo=panel; % nos=no; -end; +end xlim = get(DATA.Handles.imageaxes(panel),'xlim'); ylim = get(DATA.Handles.imageaxes(panel),'ylim'); -for ploop=panelstodo; +for ploop=panelstodo switch DATA.ViewPanelsType{ploop} case 'montage' SET(DATA.ViewPanels(ploop)).MontageZoomState = [xlim(:);ylim(:)]; @@ -2692,13 +1422,13 @@ function zoomhelper(ax,f,no,panel) SET(DATA.ViewPanels(ploop)).MontageRowZoomState = [xlim(:);ylim(:)]; case {'montagefit','sax3','montagesegmented'} SET(DATA.ViewPanels(ploop)).MontageFitZoomState = [xlim(:);ylim(:)]; - case {'one','ortho'} + case {'one','orth'} SET(DATA.ViewPanels(ploop)).NormalZoomState = [xlim(:);ylim(:)]; case 'hla' SET(DATA.ViewPanels(ploop)).HLA.ZoomState = [xlim(:);ylim(:)]; case 'vla' SET(DATA.ViewPanels(ploop)).VLA.ZoomState = [xlim(:);ylim(:)]; - end; + end end %set dataaspectratio so that adjustment in zooming does not affect the @@ -2729,15 +1459,15 @@ function zoomhelper(ax,f,no,panel) return end -if strcmp(get(gcbf,'currentmodifier'),'shift'), +if strcmp(get(gcbf,'currentmodifier'),'shift') for loop=1:length(DATA.Handles.imageaxes) zoomhelper(DATA.Handles.imageaxes(loop),1.2,DATA.ViewPanels(loop),loop); end else zoomhelper(DATA.Handles.imageaxes(DATA.CurrentPanel),1.2); end -drawfunctions('viewupdatetextposition'); -drawfunctions('viewupdateannotext'); +%drawfunctions('viewupdatetextposition'); +%drawfunctions('viewupdateannotext'); %---------------------------- function viewzoomout_Callback %#ok @@ -2755,15 +1485,15 @@ function zoomhelper(ax,f,no,panel) return end -if strcmp(get(gcbf,'currentmodifier'),'shift'), +if strcmp(get(gcbf,'currentmodifier'),'shift') for loop=1:length(DATA.Handles.imageaxes) zoomhelper(DATA.Handles.imageaxes(loop),1/1.2,DATA.ViewPanels(loop),loop); end else zoomhelper(DATA.Handles.imageaxes(DATA.CurrentPanel),1/1.2); end -drawfunctions('viewupdatetextposition'); -drawfunctions('viewupdateannotext'); +%drawfunctions('viewupdatetextposition'); +%drawfunctions('viewupdateannotext'); %-------------------------------------- function viewpandir_Callback(direction) %#ok @@ -2784,280 +1514,10 @@ function viewpandir_Callback(direction) %#ok xlim = xlim+xchange; case 'right' xlim = xlim-xchange; -end; +end set(ca,'xlim',xlim,'ylim',ylim); -%------------------------------ -function viewhidepanel_Callback %#ok -%------------------------------ -%Hides current panel -global DATA - -if length(DATA.ViewPanels)==1 - myfailed('If hiding this panel then no panels will be visible.',DATA.GUI.Segment); - return; -end; - -DATA.ViewPanels(DATA.CurrentPanel) = 0; -DATA.ViewPanelsType{DATA.CurrentPanel} = ''; -DATA.ViewIM{DATA.CurrentPanel} = []; -DATA.Overlay(DATA.CurrentPanel) = struct('alphadata',[],'cdata',[]); -drawfunctions('drawall',DATA.ViewMatrix); - -%--------------------------------------- -function viewhideimagestack_Callback(no) %#ok -%--------------------------------------- -%Remove clicked image stack from view panels -global DATA SET - -if nargin==0 - %Clicked position is still valid. - no = getclickedpreview;%should possibly be removed as in fileclosecurrentimagestack -% p = get(gca,'CurrentPoint'); -% x=p(1); -% no = floor(x/DATA.GUISettings.ThumbnailSize)+1; -end; - -if (no<1)||(no>length(SET)) - return; -end; - -if not(any(DATA.ViewPanels==no)) - myfailed('Can not hide a non visible image stack',DATA.GUI.Segment); - return; -end; - -lind = (DATA.ViewPanels~=no)&DATA.ViewPanels; %The last removes 0 -if not(sum(lind)>0) - myfailed('If removing this image stack then no image stacks will be visible.',DATA.GUI.Segment); - return; -end; - -DATA.ViewPanels(lind) = 0; -DATA.ViewPanelsType{lind} = ''; -DATA.ViewIM{lind} = []; -DATA.Overlay(lind) = struct('alphadata',[],'cdata',[]); -DATA.CurrentPanel = 1; - -drawfunctions('drawall',DATA.ViewMatrix); - -%----------------------------------- -function viewimagestack_Callback(no) %#ok -%----------------------------------- -%Make clicked image stack visible -global DATA SET - -if nargin==0 - %Clicked position is still valid. - no = getclickedpreview;%should possibly be removed as in fileclosecurrentimagestack -end; - -if (no<1)||(no>length(SET)) - return; -end; - -addtopanels(no); -drawfunctions('drawall',length(DATA.ViewPanels)); - -%----------------------------------- -function viewallimagestacks_Callback -%----------------------------------- -%Displays all image stacks. -global DATA SET - -DATA.ViewPanels = []; -DATA.ViewPanelsType = {}; -DATA.ViewPanelsMatrix = {}; -DATA.ViewIM = {}; -DATA.Overlay = []; -DATA.CurrentPanel = 1; - -for loop=1:length(SET) - addtopanels(loop); -end; -drawfunctions('drawall',length(DATA.ViewPanels)); - -%-------------------------------- -function viewimage_Callback(type) -%-------------------------------- -%Select type of image to view on screen. -global DATA SET NO -if DATA.Silent - return; -end; - -panel = DATA.CurrentPanel; - -oldmode = DATA.ViewPanelsType{panel}; - -if nargin==0 - type = oldmode; -end; - -doall = false; -if ismember(oldmode,{'mmodetemporal','mmodespatial'}) || ... - ismember(oldmode,{'ortho','hla','vla','gla'}) - %Old mode is mmode or orthoview, clear it. - ind = true(1,length(DATA.ViewPanelsType)); - for loop=1:length(DATA.ViewPanelsType) - if ismember(DATA.ViewPanelsType{loop},{'mmodespatial','ortho'}) - panel = loop; %Keep this. - DATA.CurrentPanel = panel; - DATA.ViewPanelsType{loop} = 'one'; %Change from mmode to one - end; - if ismember(DATA.ViewPanelsType{loop},{'mmodetemporal','hla','vla','gla'}) - ind(loop) = false; %Mark for deletion - end; - end; - DATA.ViewPanels = DATA.ViewPanels(ind); - DATA.ViewPanelsType = DATA.ViewPanelsType(ind); - DATA.ViewPanelsMatrix = DATA.ViewPanelsMatrix(ind); - DATA.ViewIM = DATA.ViewIM(ind); - DATA.Overlay = DATA.Overlay(ind); - doall = true; %Update complete screen since one panel is removed. - DATA.CurrentPanel = 1; - if strcmp(DATA.CurrentTool,'orthoview') - updatetool('select'); - end -end; - -switch type - case {'one','ortho','hla','vla'} - - if length(SET(DATA.ViewPanels(panel)).Linked) > 1 - nos = SET(DATA.ViewPanels(panel)).Linked; - panelstodo=find(ismember(DATA.ViewPanels,nos)); - nos=DATA.ViewPanels(panelstodo); - else - panelstodo=panel; - nos=NO; - end; - - for loop=1:length(panelstodo) - panelloop=panelstodo(loop); - no=nos(loop); - - DATA.ViewPanelsType{panelloop} = type; - SET(no).StartSlice = SET(no).CurrentSlice; - SET(no).EndSlice = SET(no).CurrentSlice; - DATA.ViewIM{panelloop} = []; - DATA.Overlay(panelloop) = struct('alphadata',[],'cdata',[]); - makeviewim(panelloop,no); - end - - if doall - drawfunctions('drawall'); - else - drawfunctions('drawimageno',DATA.ViewPanels(panel)); - end; - - case 'mmode' - for loop=1:length(DATA.ViewPanelsType) - if isequal(DATA.ViewPanelsType{loop},'mmodespatial') - DATA.ViewPanelsType{loop} = 'one'; - end - if isequal(DATA.ViewPanelsType{loop},'mmodetemporal') - %remove existing mmode images - DATA.ViewPanels(loop) = []; - DATA.ViewPanelsType(loop) = []; - DATA.ViewPanelsMatrix(loop) = []; - DATA.ViewIM(loop) = []; - DATA.Overlay(loop) = []; - if panel > loop - panel = panel-1; - DATA.CurrentPanel = panel; - end - break - %myfailed('Can not have two mmode images visible at the same time.',DATA.GUI.Segment); - %return; - end; - end; - if SET(NO).TSize>1 - - DATA.ViewPanelsType{panel} = 'mmodespatial'; - SET(NO).StartSlice = SET(NO).CurrentSlice; - SET(NO).EndSlice = SET(NO).CurrentSlice; - - DATA.ViewIM{panel} = []; %Remove is montage - empol = struct('alphadata',[],'cdata',[]); - DATA.Overlay(panel) = empol; - - %switch position to make mmodespatial first - pos = 1; - temp=DATA.ViewPanels(panel); DATA.ViewPanels(panel)=DATA.ViewPanels(pos); DATA.ViewPanels(pos)=temp; - temp=DATA.ViewPanelsType{panel}; DATA.ViewPanelsType{panel}=DATA.ViewPanelsType{pos}; DATA.ViewPanelsType{pos}=temp; - temp=DATA.ViewIM{panel}; DATA.ViewIM{panel}=DATA.ViewIM{pos}; DATA.ViewIM{pos}=temp; - DATA.CurrentPanel = 1; - - %Add view panel mmodetemporal as number second - DATA.ViewPanels = cat(2,DATA.ViewPanels(1),DATA.ViewPanels(1),DATA.ViewPanels(2:end)); - DATA.ViewPanelsType = cat(2,DATA.ViewPanelsType(1),{'mmodetemporal'},DATA.ViewPanelsType(2:end)); - DATA.ViewPanelsMatrix = cat(2,DATA.ViewPanelsMatrix(1),{[]},DATA.ViewPanelsMatrix(2:end)); - DATA.ViewIM = cat(2,DATA.ViewIM(1),{[]},DATA.ViewIM(2:end)); - DATA.Overlay = cat(2,DATA.Overlay(1),empol,DATA.Overlay(2:end)); - else - viewimage_Callback('one'); - end; - drawfunctions('drawall'); - case 'montage' - - if length(SET(DATA.ViewPanels(panel)).Linked) > 1 - nos = SET(DATA.ViewPanels(panel)).Linked; - panelstodo=find(ismember(DATA.ViewPanels,nos)); - nos=DATA.ViewPanels(panelstodo); - else - panelstodo=panel; - nos=NO; - end; - - for loop=1:length(panelstodo) - panelloop=panelstodo(loop); - no=nos(loop); - DATA.ViewPanelsType{panelloop} = type; - DATA.ViewIM{panelloop} = []; - DATA.Overlay(panelloop) = struct('alphadata',[],'cdata',[]); - makeviewim(panelloop,no); - end; - - updatemodeldisplay; - if doall - drawfunctions('drawall'); - else - drawfunctions('drawimageno',DATA.ViewPanels(panel)); - end; - - case {'montagerow','montagefit','sax3','montagesegmented'} - DATA.ViewPanelsType{panel} = type; - DATA.ViewIM{panel} = []; - DATA.Overlay(panel) = struct('alphadata',[],'cdata',[]); - makeviewim(panel,NO); - updatemodeldisplay; - if strcmp(type,'montagefit') - centeronslice(SET(NO).CurrentSlice,NO,SET(NO).ZSize); - end - if doall - drawfunctions('drawall'); - else - drawfunctions('drawimagepanel',DATA.CurrentPanel); - end; - otherwise - myfailed('Unknown option to viewimage.',DATA.GUI.Segment); - return; -end; - -%indent the correct viewbutton -switch type - case 'one' - DATA.Handles.permanenticonholder.indent('viewone',0) - case 'montage' - DATA.Handles.permanenticonholder.indent('viewall',0) - case 'montagesegmented' - DATA.Handles.permanenticonholder.indent('viewlv',0) -end -drawfunctions('showedits',NO); -drawfunctions('drawintersections'); - %-------------------------------------- function viewmanualinteraction_Callback %#ok %-------------------------------------- @@ -3068,15 +1528,11 @@ function viewimage_Callback(type) if isempty(SET(NO).EndoX) || all(isnan(SET(NO).EndoX(:))) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; - -fig = openfig('manualedit.fig','reuse'); -myadjust(fig,DATA.GUI.Segment); -set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); +end +fig = mygui('manualedit.fig'); % Generate a structure of handles to pass to callbacks, and store it. -handles = guihandles(fig); - +handles = fig.handles; %Fix colors im = zeros(SET(NO).ZSize,SET(NO).TSize); for zloop=1:SET(NO).ZSize @@ -3103,17 +1559,17 @@ function viewimage_Callback(type) im(zloop,tloop,1) = 1; %r im(zloop,tloop,2) = 0; %g im(zloop,tloop,3) = 0; %b - end; - end; - end; - end; -end; + end + end + end + end +end -axes(handles.endoaxes); %#ok +axes(handles.endoaxes); image([1 SET(NO).TSize]-0.5,[1 SET(NO).ZSize]-0.5,im); set(gca,'xtick',1:SET(NO).TSize,'ytick',1:SET(NO).ZSize); -ylabel('Apex => Base'); -xlabel('Timeframe'); +ylabel(dprintf('Apex => Base')); +xlabel(dprintf('Timeframe')); grid on; %Fix colors epi @@ -3142,19 +1598,30 @@ function viewimage_Callback(type) im(zloop,tloop,1) = 1; %r im(zloop,tloop,2) = 0; %g im(zloop,tloop,3) = 0; %b - end; - end; - end; - end; -end; + end + end + end + end +end -axes(handles.epiaxes); %#ok +axes(handles.epiaxes); image([1 SET(NO).TSize]-0.5,[1 SET(NO).ZSize]-0.5,im); set(gca,'xtick',1:SET(NO).TSize,'ytick',1:SET(NO).ZSize); -ylabel('Apex => Base'); -xlabel('Timeframe'); +ylabel(dprintf('Apex => Base'), 'Color', DATA.GUISettings.ForegroundColor); +xlabel(dprintf('Timeframe'), 'Color', DATA.GUISettings.ForegroundColor); grid on; +%Make plot axis color match Segment's theme +set([handles.endoaxes handles.epiaxes],... + 'XColor', DATA.GUISettings.ForegroundColor,... + 'YColor', DATA.GUISettings.ForegroundColor); + +%Set legend color +set(handles.frame1,'Backgroundcolor', [0 0 1]); %blue +set(handles.frame2,'Backgroundcolor', [1 0 1]); %pink +set(handles.frame3,'Backgroundcolor', [1 0 0]); %red +set(handles.frame4,'Backgroundcolor', [0 1 1]); %cyan + %----------------------------------- function figure_DeleteFcn %#ok %----------------------------------- @@ -3177,161 +1644,11 @@ function viewimage_Callback(type) t = SET(NO).CurrentTimeFrame+1; if t>SET(NO).TSize t = 1; - end; + end else %User timer info t = 1+mod(floor(rem(now-DATA.StartTime,1)*24*3600/(SET(NO).BeatTime/SET(NO).TSize)+DATA.StartFrame),SET(NO).TSize); -end; - -%------------------------------------ -function selectallslices_Callback(no) -%------------------------------------ -%Selects all slices in current image stack -global SET NO - -if nargin == 0 -no=NO; -end - -SET(no).StartSlice = 1; -SET(no).EndSlice = SET(no).ZSize; -segment('updateselectedslices'); - -%-------------------------------------- -function unselectallslices_Callback(no) -%-------------------------------------- -%Unselects slices in current image stack -global SET NO - -if nargin == 0 - no=NO; -end - -SET(no).StartSlice = []; -SET(no).EndSlice = []; - -%SET(NO).CurrentSlice = []; -% For various reasons this is a bad idea. Many things rely on it being set, -% and difficult to gaurentee that it is set to something sensible. Best to -% check with StartSlice:EndSlice in cases where 'unselection' is desired. - -updateselectedslices; - -%--------------------- -function unlighttool(h) %#ok -%--------------------- -%Helper function to change color of a tool to represent unselected. -global DATA - -set(h,'value',0,'backgroundcolor',DATA.GUISettings.ButtonColor); -%set(h,'value',0,'backgroundcolor',[0.6 0.6 0.6]); - -%----------------------- -function highlighttool(h) -%----------------------- -%Helper function to change color of a tool to represent that the tool is -%selected. -global DATA - -%set(h,'value',1,'backgroundcolor',[1 1 1]); -% JU: ButtonSelectedColor below was [0.6 0.6 0.6] -set(h,'value',1,'backgroundcolor',DATA.GUISettings.ButtonSelectedColor); -%temp = get(h(1),'cdata'); -%temp(isnan(temp)) = 0.5; -%set(h(1),'cdata',temp); - -%------------------------------- -function doputpin_Callback(type) -%------------------------------- -%Put pins. Called when clicked, puts an pin and refines. -global DATA SET NO - -if nargin==0 - type = 'endo'; -end; - -if nargin<2 - dolv=true; -end; - -switch type - case 'endo' - isendo = true; - dolv = true; - case 'epi' - isendo = false; - dolv = true; - case 'rvendo' - isendo = true; - dolv = false; -end; - -[x,y,slice] = getclickedcoords; -% If slice has changed, make sure montage/one are in sync -if (slice>SET(NO).ZSize) - return; end -switchtoslice(slice); - -tools('enableundo'); - -if dolv - %LV - if isendo - if isempty(SET(NO).EndoPinX) - SET(NO).EndoPinX = cell(SET(NO).TSize,SET(NO).ZSize); - SET(NO).EndoPinY = cell(SET(NO).TSize,SET(NO).ZSize); - end; - SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice} = [... - SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice} ; ... - y]; - SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice} = [... - SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice} ; ... - x]; - if (~DATA.ThisFrameOnly)&&(SET(NO).TSize>1) - lvpeter('segmentrefineendo_Callback',false,true); - end; - - else - if isempty(SET(NO).EpiPinX) - SET(NO).EpiPinX = cell(SET(NO).TSize,SET(NO).ZSize); - SET(NO).EpiPinY = cell(SET(NO).TSize,SET(NO).ZSize); - end; - SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice} = [... - SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice} ; ... - y]; - SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice} = [... - SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice} ; ... - x]; - - if (~DATA.ThisFrameOnly)&&(SET(NO).TSize>1) - lvpeter('segmentrefineepi_Callback',false); - end; - end; -else - %RV - if isendo - if isempty(SET(NO).RVEndoPinX) - SET(NO).RVEndoPinX = cell(SET(NO).TSize,SET(NO).ZSize); - SET(NO).RVEndoPinY = cell(SET(NO).TSize,SET(NO).ZSize); - end; - SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice} = [... - SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice} ; ... - y]; - SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice} = [... - SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice} ; ... - x]; - - if (~DATA.ThisFrameOnly) && (SET(NO).TSize>1) - rv('segmentrefinervendo_Callback',false,true); - end; - end; -end; - -checkconsistency; -updateselectedslices; -updatemodeldisplay; -drawfunctions('drawsliceno'); %----------------------------- function volumeaxes_Buttondown %#ok @@ -3341,7 +1658,7 @@ function doputpin_Callback(type) global DATA SET NO -if any(NO == DATA.LVNO) +if any(NO == DATA.LVNO) || strcmp(DATA.ProgramName,'Segment') [x,y] = mygetcurrentpoint(gca); % t = round((x/1000+1.5*SET(NO).TIncr)/(SET(NO).TIncr)); @@ -3356,16 +1673,21 @@ function doputpin_Callback(type) if abs(ylim(2)-y)<(0.2*(ylim(2)-ylim(1))) esed_Buttondown('ed'); return; - end; - end; + end + end if abs(SET(NO).EST-t)<3 if abs(y-(0.25*(ylim(2)-ylim(1))+ylim(1)))<(0.2*(ylim(2)-ylim(1))) %ES textg is not really at bottom. esed_Buttondown('es'); return; - end; - end; + end + end DATA.updatevolumeaxes; - drawfunctions('drawsliceno'); + panels = find(DATA.ViewPanels == NO); + for p = panels + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p); + end + viewfunctions('updatetimebars') end %-------------------------- @@ -3375,11 +1697,9 @@ function esed_Buttonup(type) %#ok global DATA SET NO -if any(NO == DATA.LVNO) +if any(NO == DATA.LVNO) || strcmp(DATA.ProgramName,'Segment') %Get position [x] = mygetcurrentpoint(gca); -% t = round((x/1000+1.5*SET(NO).TIncr)/(SET(NO).TIncr)); -% t = max(min(t,SET(NO).TSize),1); xlim=get(DATA.Handles.timebaraxes,'xlim'); [~,t]=min((SET(NO).TimeVector/SET(NO).TimeVector(end)-x/xlim(2)).^2); t=max([t,1]); @@ -3389,18 +1709,35 @@ function esed_Buttonup(type) %#ok SET(NO).EST = t; case 'ed' SET(NO).EDT = t; - end; + end %disp(sprintf('ed:%d es:%d',SET(NO).EDT,SET(NO).EST)); %Restore - set(DATA.fig,'WindowButtonUpFcn','segment(''buttonup_Callback'')'); + set(DATA.fig,'WindowButtonUpFcn','buttonupfunctions(''buttonup_Callback'')'); set(DATA.fig,'WindowButtonMotionFcn',''); SET(NO).CurrentTimeFrame = t; DATA.updatevolumeaxes - DATA.measurementreportupdate + %we also need to update the timebar ed es + switch type + case 'es' + p = get(DATA.Handles.estimebartext,'position'); + p(1) = SET(NO).TimeVector(t)*1000; + set(DATA.Handles.estimebartext,'position',p); + set(DATA.Handles.estimebarline,'XData',[SET(NO).TimeVector(t),SET(NO).TimeVector(t)]*1000); + case 'ed' + p = get(DATA.Handles.edtimebartext,'position'); + p(1) = SET(NO).TimeVector(t)*1000; + set(DATA.Handles.edtimebartext,'position',p); + set(DATA.Handles.edtimebarline,'XData',[SET(NO).TimeVector(t),SET(NO).TimeVector(t)]*1000); + end + updatevolume; - drawfunctions('drawsliceno'); + for p = find(DATA.ViewPanels==NO) + drawfunctions('drawpanel',p); + end + + viewfunctions('updatetimebars') end %------------------------- @@ -3409,29 +1746,33 @@ function esed_Motion(type) %#ok %Motion function when dragging ES or ED markers in volume graph. global DATA SET NO -if any(NO == DATA.LVNO) +if any(NO == DATA.LVNO) || strcmp(DATA.ProgramName,'Segment') [x] = mygetcurrentpoint(gca); -% t = round((x/1000+1.5*SET(NO).TIncr)/(SET(NO).TIncr)); -% t = max(min(t,SET(NO).TSize),1); xlim=get(DATA.Handles.timebaraxes,'xlim'); [~,t]=min((SET(NO).TimeVector/SET(NO).TimeVector(end)-x/xlim(2)).^2); t=max([t,1]); switch type case 'es' p = get(DATA.Handles.estext,'position'); - p(1) = x; + p(1) = SET(NO).TimeVector(t)*1000; set(DATA.Handles.estext,'position',p); SET(NO).EST = t; + set(DATA.Handles.esline,'xdata',[p(1) p(1)]); case 'ed' p = get(DATA.Handles.edtext,'position'); - p(1) = x; + p(1) = SET(NO).TimeVector(t)*1000; set(DATA.Handles.edtext,'position',p); SET(NO).EDT = t; - end; + set(DATA.Handles.edline,'xdata',[p(1) p(1)]); + end SET(NO).CurrentTimeFrame = t; - drawfunctions('drawsliceno'); - + panels = find(DATA.ViewPanels == NO); + for p = panels + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p); + end + end %----------------------------- @@ -3440,7 +1781,7 @@ function esed_Buttondown(type) %Buttondown function when dragging ES or ED markers in volume graph. global DATA SET NO -if any(NO == DATA.LVNO) +if any(NO == DATA.LVNO) || strcmp(DATA.ProgramName,'Segment') switch lower(type) case 'ed' set(DATA.fig,'WindowButtonUpFcn',... @@ -3454,7 +1795,7 @@ function esed_Buttondown(type) set(DATA.fig,'WindowButtonMotionFcn',... 'segment(''esed_Motion'',''es'')'); SET(NO).CurrentTimeFrame = SET(NO).EST; - end; + end end %----------------------------- @@ -3478,28 +1819,32 @@ function esed_Buttondown(type) if abs(ylim(2)-y)<(0.2*(ylim(2)-ylim(1))) esedtimebar_Buttondown('ed'); return; - end; -end; + end +end if abs(SET(NO).EST-t)<3 if abs(y-(0.25*(ylim(2)-ylim(1))+ylim(1)))<(0.2*(ylim(2)-ylim(1))) %ES textg is not really at bottom. esedtimebar_Buttondown('es'); return; - end; -end; + end +end nos = SET(NO).Linked; for loop=setdiff(nos,NO) SET(loop).CurrentTimeFrame = SET(NO).CurrentTimeFrame; if SET(loop).CurrentTimeFrame > SET(loop).TSize SET(loop).CurrentTimeFrame = SET(loop).TSize; - end; -end; + end +end -for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop)); -end; +for p = find(ismember(DATA.ViewPanels,nos)) + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p); +end -% drawfunctions('drawsliceno'); +%update timebars +viewfunctions('updatetimebars') +set(DATA.fig,'WindowButtonUpFcn','buttonupfunctions(''buttonup_Callback'')'); +set(DATA.fig,'WindowButtonMotionFcn','segment(''timebar_Motion'')'); %-------------------------- function esedtimebar_Buttonup(type) %#ok @@ -3521,14 +1866,21 @@ function esedtimebar_Buttonup(type) %#ok SET(NO).EST = t; case 'ed' SET(NO).EDT = t; -end; +end %Restore -set(DATA.fig,'WindowButtonUpFcn','segment(''buttonup_Callback'')'); -set(DATA.fig,'WindowButtonMotionFcn',''); +set(DATA.fig,'WindowButtonUpFcn','buttonupfunctions(''buttonup_Callback'')'); +set(DATA.fig,'WindowButtonMotionFcn',@DATA.toggleplaceholdermotion); SET(NO).CurrentTimeFrame = t; updatevolume; -drawfunctions('drawsliceno'); +panels = find(DATA.ViewPanels == NO); +for p = panels + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p); +end + +%update timebars +viewfunctions('updatetimebars') %------------------------- function esedtimebar_Motion(type) %#ok @@ -3537,8 +1889,6 @@ function esedtimebar_Motion(type) %#ok global DATA SET NO [x] = mygetcurrentpoint(gca); -% t = round((x/1000+1.5*SET(NO).TIncr)/(SET(NO).TIncr)); -% t = max(min(t,SET(NO).TSize),1); xlim=get(DATA.Handles.timebaraxes,'xlim'); [~,t]=min((SET(NO).TimeVector/SET(NO).TimeVector(end)-x/xlim(2)).^2); t=max([t,1]); @@ -3546,18 +1896,27 @@ function esedtimebar_Motion(type) %#ok switch type case 'es' p = get(DATA.Handles.estimebartext,'position'); - p(1) = x; + p(1) = SET(NO).TimeVector(t)*1000; set(DATA.Handles.estimebartext,'position',p); - SET(NO).EST = t; + SET(NO).EST = t; + set(DATA.Handles.estimebarline,'XData',[SET(NO).TimeVector(t),SET(NO).TimeVector(t)]*1000); case 'ed' p = get(DATA.Handles.edtimebartext,'position'); - p(1) = x; + p(1) = SET(NO).TimeVector(t)*1000; set(DATA.Handles.edtimebartext,'position',p); SET(NO).EDT = t; -end; + set(DATA.Handles.edtimebarline,'XData',[SET(NO).TimeVector(t),SET(NO).TimeVector(t)]*1000); +end SET(NO).CurrentTimeFrame = t; -drawfunctions('drawsliceno'); +panels = find(DATA.ViewPanels == NO); +for p = panels + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p); +end + +%update timebars +viewfunctions('updatetimebars') %----------------------------- function esedtimebar_Buttondown(type) @@ -3578,7 +1937,10 @@ function esedtimebar_Buttondown(type) set(DATA.fig,'WindowButtonMotionFcn',... 'segment(''esedtimebar_Motion'',''es'')'); SET(NO).CurrentTimeFrame = SET(NO).EST; -end; +end + +%update timebars +viewfunctions('updatetimebars') %----------------------------- function flowaxes_Buttondown %#ok @@ -3588,7 +1950,7 @@ function esedtimebar_Buttondown(type) global DATA SET NO -if ismember(NO,SET(DATA.FlowNO).Linked) +if ismember(NO,SET(DATA.FlowNO).Linked) || strcmp(DATA.ProgramName,'Segment') [x,y] = mygetcurrentpoint(gca); % t = round((x/1000+1.5*SET(NO).TIncr)/(SET(NO).TIncr)); @@ -3602,89 +1964,18 @@ function esedtimebar_Buttondown(type) SET(loop).CurrentTimeFrame = SET(NO).CurrentTimeFrame; if SET(loop).CurrentTimeFrame > SET(loop).TSize SET(loop).CurrentTimeFrame = SET(loop).TSize; - end; - end; - - DATA.updateflowaxes; + end + end + + panels = find(ismember(DATA.ViewPanels ,nos)); + for p = panels + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p); + end - for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop)); - end; -% drawfunctions('drawsliceno'); + viewfunctions('updatetimebars') end -%------------------------------------- -function clickedpin_Callback(type) %#ok -%------------------------------------- -%Called when user clicks on a pin. -global DATA SET NO - -%Check what type of click -switch get(DATA.imagefig,'SelectionType') - case 'normal' - [x,y,slice] = getclickedcoords; - - %Find what pin. - switch type - case 'endo' - if isempty(SET(NO).EndoPinX) - return; %Not sure if can happen, but... - end; - xm = SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice}; - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''pin_Motion'',''endo'')',mfilename)); - case 'epi' - if isempty(SET(NO).EpiPinX) - return; %Not sure if can happen, but... - end; - xm = SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice}; - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''pin_Motion'',''epi'')',mfilename)); - case 'rvendo' - if isempty(SET(NO).RVEndoPinX) - return; %Not sure if can happen, but... - end; - xm = SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice}; - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''pin_Motion'',''rvendo'')',mfilename)); - case 'rvepi' - %EiHMOD: Bug report from Lene R - if isempty(SET(NO).RVEpiPinX) - return; %Not sure if can happen, but... - end; - xm = SET(NO).RVEpiPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).RVEpiPinY{SET(NO).CurrentTimeFrame,slice}; - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''pin_Motion'',''rvepi'')',mfilename)); - end; - set(DATA.imagefig,'WindowButtonUpFcn','segment(''pin_Buttonup'')'); - - %Calculate distance - [~,tempind] = min(sqrt((xm-y).^2+(ym-x).^2)); - DATA.Pin = tempind; %Store what pin - - case 'alt' - DATA.contextmenu; -% p = get(DATA.imagefig,'CurrentPoint'); -% switch type -% case 'endo' -% set(DATA.Handles.endopinmenu,... -% 'Position',p,... -% 'Visible','on'); -% case 'epi' -% set(DATA.Handles.epipinmenu,... -% 'Position',p,... -% 'Visible','on'); -% case 'rvendo' -% set(DATA.Handles.rvendopinmenu,... -% 'Position',p,... -% 'Visible','on'); -% end; -end; - %------------------------------ function ok = enablecalculation %#ok %------------------------------ @@ -3703,100 +1994,23 @@ function clickedpin_Callback(type) %#ok if SET(NO).ZSize==1 SET(NO).StartSlice = 1; SET(NO).EndSlice = 1; - end; + end ok = true; DATA.Interactionlock = true; else ok = false; myworkoff; - mydisp('Warning: No slices selected => command ignored.'); -end; + disp('Warning: No slices selected => command ignored.'); +end %------------------------- -function endoffcalculation +function endoffcalculation %#ok %------------------------- %Turns off interaction lock, called after a calculation. See above. global DATA DATA.Interactionlock = false; myworkoff; -%------------------------------- -function viewrefreshall_Callback %#ok -%------------------------------- -%Main refresh of GUI -global DATA SET NO - -mydisp('Full screen refresh'); -flushlog; - -%To avoid if a button up function is not run. -set(DATA.fig,'WindowButtonMotionFcn',''); - -if DATA.Silent || (~DATA.DataLoaded) - return; -end; - -try - oldNO = NO; - - for loop=1:length(SET) - SET(loop).NormalZoomState = []; - SET(loop).MontageZoomState = []; - SET(loop).MontageRowZoomState = []; - end; - - %--- - try - delete(DATA.Handles.thumbnailimage); - catch %#ok - end - - try - delete(DATA.Handles.thumbnaildragaxes); - catch %#ok - end - %--- - checkconsistency; %if any problem with LV/RV seg, this should fix it - updatemodeldisplay; - drawfunctions('drawall',DATA.ViewMatrix); - DATA.updatetitle; - updatetool('select'); - endoffcalculation; - DATA.switchtoimagestack(oldNO); -catch me - disp('Could not perform refresh'); - mydispexception(me); -end; - -flushlog; - -set(DATA.fig,'WindowButtonMotionFcn','segment(''toggleplaceholdermotion'')'); - -%----------------------------- -function viewrefresh_Callback -%----------------------------- -%Main graphical refresh. -global DATA SET NO - -set(DATA.Handles.refreshicon,'State','off'); -set([... - DATA.Handles.hideroiicon ... - DATA.Handles.hidelvicon ... - DATA.Handles.hidervicon ... - DATA.Handles.hidescaricon ... - DATA.Handles.hidemaricon],'state','off'); - -SET(NO).NormalZoomState = []; -SET(NO).MontageZoomState = []; -SET(NO).MontageRowZoomState = []; - -DATA.updatetitle; -drawfunctions('drawimageno'); -updatevolume; -updatemodeldisplay; -updatetool('select'); -endoffcalculation; - %-------------------------------------- function plotmodelrot_Callback(daz,del) %#ok %-------------------------------------- @@ -3813,7 +2027,7 @@ function plotmodelrot_Callback(daz,del) %#ok drawnow; DATA.MovieFrame = mygetframe(4); export('exportmovierecorder_Callback','newframe'); -end; +end %------------------------------ function updatemmodevisibility %#ok @@ -3826,7 +2040,7 @@ function plotmodelrot_Callback(daz,del) %#ok if (SET(NO).TSize<2)||(isequal(DATA.ViewPanelsType{DATA.CurrentPanel},'flow')) rightstate = 'off'; -end; +end %Apply settings @@ -3869,7 +2083,7 @@ function plotmodelrot_Callback(daz,del) %#ok set(DATA.Handles.mmodetimebar2,... 'xdata',[1 1]*SET(NO).Mmode.T2); %updates the text -DATA.updateaxestables('measure'); +% DATA.updateaxestables('measure'); % set(DATA.Handles.distancetext,'string',... % sprintf('Distance:%3.2f [mm]\tTime:%3.2f [ms]',dist,timedist)); @@ -3881,7 +2095,7 @@ function updatemmode(arg,nbrofcycles) if SET(NO).TSize<2 return; -end; +end onecycle = true; if nargin == 2 @@ -3932,13 +2146,13 @@ function updatemmode(arg,nbrofcycles) for tloop=1:SET(NO).TSize temp(:,tloop + SET(NO).TSize*[0 1 2]) = repmat(interp2( ... SET(NO).IM(:,:,tloop,SET(NO).CurrentSlice),xi,yi)',1,3); - end; + end else for tloop=1:SET(NO).TSize temp(:,tloop + SET(NO).TSize*[0 1 2]) = repmat(interp2( ... SET(NO).IM(:,:,tloop,SET(NO).CurrentSlice),xi,yi,'nearest')',1,3); - end; -end; + end +end %Display data temp = calcfunctions('remapuint8',temp,NO); @@ -3947,8 +2161,8 @@ function updatemmode(arg,nbrofcycles) for loop=1:length(DATA.ViewPanelsType) if isequal(DATA.ViewPanelsType{loop},'mmodetemporal') panel = loop; - end; -end; + end +end if not(isempty(panel)) set(DATA.Handles.imagehandle(panel),'cdata',temp); if dozoom @@ -3961,7 +2175,7 @@ function updatemmode(arg,nbrofcycles) end axis(DATA.Handles.imageaxes(panel),imax); end -end; +end %-------------------------- function mmodecenter_Motion %#ok @@ -4083,158 +2297,158 @@ function updatemmode(arg,nbrofcycles) %Update mmode display updatemmode; -%------------------------------------- -function mmodecenter_Buttondown(panel) %#ok -%------------------------------------- -%Called when mmode center is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodecenter_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%-------------------------------- -function mmode1_Buttondown(panel) %#ok -%-------------------------------- -%Called when mmode1 is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode1_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%-------------------------------- -function mmode2_Buttondown(panel) %#ok -%-------------------------------- -%Called when mmode1 is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode2_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%------------------------------------ -function mmode1line_Buttondown(panel) %#ok -%------------------------------------ -%Called when mmode1line is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode1line_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%------------------------------------ -function mmode2line_Buttondown(panel) %#ok -%------------------------------------ -%Called when mmode1line is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode2line_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%------------------------------------- -function mmodepoint1_Buttondown(panel) %#ok -%------------------------------------- -%Called when mmodepoint1 is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodempoint1_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%------------------------------------- -function mmodepoint2_Buttondown(panel) %#ok -%------------------------------------- -%Called when mmodepoint1 is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodempoint2_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%--------------------------------------- -function mmodetimebar1_Buttondown(panel) %#ok -%--------------------------------------- -%Called when mmodepoint1 is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodetimebar1_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); - -%--------------------------------------- -function mmodetimebar2_Buttondown(panel) %#ok -%--------------------------------------- -%Called when mmodepoint1 is pressed down, sets motion and buttonup -%function. -global DATA - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodetimebar2_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''mmode_Buttonup'')',mfilename)); +% %------------------------------------- +% function mmodecenter_Buttondown(panel) %#ok +% %------------------------------------- +% %Called when mmode center is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodecenter_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %-------------------------------- +% function mmode1_Buttondown(panel) %#ok +% %-------------------------------- +% %Called when mmode1 is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode1_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %-------------------------------- +% function mmode2_Buttondown(panel) %#ok +% %-------------------------------- +% %Called when mmode1 is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode2_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %------------------------------------ +% function mmode1line_Buttondown(panel) %#ok +% %------------------------------------ +% %Called when mmode1line is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode1line_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %------------------------------------ +% function mmode2line_Buttondown(panel) %#ok +% %------------------------------------ +% %Called when mmode1line is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmode2line_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %------------------------------------- +% function mmodepoint1_Buttondown(panel) %#ok +% %------------------------------------- +% %Called when mmodepoint1 is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodempoint1_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %------------------------------------- +% function mmodepoint2_Buttondown(panel) %#ok +% %------------------------------------- +% %Called when mmodepoint1 is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodempoint2_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %--------------------------------------- +% function mmodetimebar1_Buttondown(panel) %#ok +% %--------------------------------------- +% %Called when mmodepoint1 is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodetimebar1_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); +% +% %--------------------------------------- +% function mmodetimebar2_Buttondown(panel) %#ok +% %--------------------------------------- +% %Called when mmodepoint1 is pressed down, sets motion and buttonup +% %function. +% global DATA +% +% switchtopanel(panel); +% +% if DATA.Interactionlock +% return; +% end +% +% set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''mmodetimebar2_Motion'');',mfilename)); +% set(DATA.imagefig,'WindowButtonUpFcn',... +% sprintf('%s(''mmode_Buttonup'')',mfilename)); %------------------------- function setcurrenttimeframe(frame) %#ok @@ -4248,263 +2462,83 @@ function setcurrenttimeframe(frame) %#ok nos = SET(NO).Linked; for loop=1:length(nos(nos~=NO)) SET(nos(loop)).CurrentTimeFrame = SET(NO).CurrentTimeFrame; -end; +end -for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop)); -end; +% for nloop=1:length(nos) +% drawfunctions('updatenopanels',nos(nloop)); +% end +viewfunctions('setview'); %updatevolume; drawnow('expose'); %Expose does not other callbacks to evaluate. -%-------------------------- -function nextframe_Callback %#ok -%-------------------------- -%Displays next timeframe of current image panel. Sideeffect is that the -%movie display is stopped if running. -global DATA SET NO -% -% set([... -% DATA.Handles.nextframeicon ... -% DATA.Handles.playmovieicon ... -% DATA.Handles.playallicon],'state','off'); - -stateandicon=segment('iconson','play'); -stateandicon{2}.undent; -DATA.Handles.permanenticonholder.render; -DATA.Run = 0; -if SET(NO).TSize<=1 - return; -end; +%----------------------------------------------------- +function [xout,yout] = checkconsistencyhelper(xin,yin,numpoints) +%----------------------------------------------------- +%Make sure that the contour is counter clock-wise and that it starts at +%three o clock. Also ensures that the points are evenly distributed. -SET(NO).CurrentTimeFrame = 1+mod(SET(NO).CurrentTimeFrame,SET(NO).TSize); +global DATA -nos = SET(NO).Linked; -for loop=setdiff(nos,NO) - SET(loop).CurrentTimeFrame = SET(NO).CurrentTimeFrame; - if SET(loop).CurrentTimeFrame > SET(loop).TSize - SET(loop).CurrentTimeFrame = SET(loop).TSize; - end; -end; +if nargin == 2 + numpoints = DATA.NumPoints; +end -for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop)); -end; +%--- Make sure evenly distributed +diffx = conv2(xin,[1;-1],'valid'); +diffy = conv2(yin,[1;-1],'valid'); +diffvec = sqrt(diffx.*diffx+diffy.*diffy); -if DATA.Record - DATA.MovieFrame = mygetframe(DATA.imagefig); - export('exportmovierecorder_Callback','newframe'); -end; +if any((diffvec-mean(diffvec))/mean(diffvec)>2) + %disp('Problem with endo => fixed, report to support'); +end +contourlength = cumsum(diffvec); +xout = interp1(contourlength,xin(2:end),linspace(contourlength(1),contourlength(end),numpoints-1)); +yout = interp1(contourlength,yin(2:end),linspace(contourlength(1),contourlength(end),numpoints-1)); +xout(end+1) = xout(1); +yout(end+1) = yout(1); -%updatevolume; -drawnow('expose'); %Expose does not other callbacks to evaluate. - -%----------------------------- -function nextallframe_Callback -%----------------------------- -%Displays next timeframe in currrent image panel and adjust all visiable -%image stacks to the corresponding part of the cardiac cycle. -global DATA SET NO -% -% set([... -% DATA.Handles.nextallframeicon ... -% DATA.Handles.playmovieicon ... -% DATA.Handles.playallicon],'state','off'); - -stateandicon=segment('iconson','play'); -stateandicon{2}.undent; -DATA.Handles.permanenticonholder.render; -DATA.Run = 0; +%--- Make sure correct rotation (starting pos) +xr = yout; +yr = xout; +mx = mean(xr); +my = mean(yr); -%if not timeresolved then return -if SET(NO).TSize<=1 - return; -end; +if sum(unwrap(conv2(angle(complex(xr-mx,yr-my)),[1;-1],'valid')))<0 + disp(sprintf('counterclockwise endo %d slice %d',timeframe,zloop)); %#ok + xr = fliplr(xr); + yr = fliplr(yr); +end -%Increase one -SET(NO).CurrentTimeFrame = SET(NO).CurrentTimeFrame+1; -if SET(NO).CurrentTimeFrame>SET(NO).TSize - SET(NO).CurrentTimeFrame = 1; -end; +[~,inda] = min(angle(complex(mx-xr,my-yr))); +xout(1:(numpoints-inda+1)) = yr(inda:end); +yout(1:(numpoints-inda+1)) = xr(inda:end); +xout((numpoints+1-inda):end) = yr(1:inda); +yout((numpoints+1-inda):end) = xr(1:inda); + +%-------------------------------------------- +function checkconsistency(timeframes,slice,no) +%--------------------------------------------- +%Check consistency, to prevent earlier +%manual segmentations that have problems with +%direction lef/right +global SET NO DATA -%Calculate percentage -percent = (SET(NO).CurrentTimeFrame-1)/(SET(NO).TSize-1); +if nargin==0 + timeframes=SET(NO).CurrentTimeFrame; %1; +end -nos = unique(DATA.ViewPanels(DATA.ViewPanels > 0)); -%Loop over all image stacks to update time. -for loop=nos%1:length(SET) - SET(loop).CurrentTimeFrame = min(max(1,1+round(percent*(SET(loop).TSize-1))),SET(loop).TSize); -end; +if nargin<2 + slice=SET(NO).CurrentSlice; +end -%Draw all panels -for no=nos([SET(nos).TSize]>1) - drawfunctions('updatenopanels',no); -end; - -updatevolume; -if DATA.Record - drawnow; - DATA.MovieFrame = mygetframe(DATA.imagefig); - export('exportmovierecorder_Callback','newframe'); -end; -drawnow('expose'); %Expose does not other callbacks to evaluate. - -%------------------------------ -function previousframe_Callback %#ok -%------------------------------ -%Displays previous time frame of current panel. -global DATA SET NO -% -% set([... -% DATA.Handles.previousframeicon ... -% DATA.Handles.playmovieicon ... -% DATA.Handles.playallicon],'state','off'); - -stateandicon=segment('iconson','play'); -stateandicon{2}.undent; -DATA.Handles.permanenticonholder.render; -DATA.Run = 0; - -if SET(NO).TSize<=1 - return; -end; - -SET(NO).CurrentTimeFrame = 1+mod(SET(NO).CurrentTimeFrame-2,SET(NO).TSize); - -nos = SET(NO).Linked; -for loop=setdiff(nos,NO) - SET(loop).CurrentTimeFrame = SET(NO).CurrentTimeFrame; - if SET(loop).CurrentTimeFrame > SET(loop).TSize - SET(loop).CurrentTimeFrame = 1; - end; -end; - -for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop)); -end; - -if DATA.Record - drawnow; - DATA.MovieFrame = mygetframe(DATA.imagefig); - export('exportmovierecorder_Callback','newframe'); -end; -drawnow('expose'); %Expose does not other callbacks to evaluate. - -%----------------------------- -function previousallframe_Callback -%----------------------------- -%Displays previous time frame in current image panel. For all other visible -%image stacks they are adjusted to show correspondig part of the cardiac -%cycle. - -global DATA SET NO -% -% set([... -% DATA.Handles.previousallframeicon ... -% DATA.Handles.playmovieicon ... -% DATA.Handles.playallicon],'state','off'); -stateandicon=segment('iconson','play'); -stateandicon{2}.undent; -DATA.Handles.permanenticonholder.render; - -DATA.Run = 0; - -%if not timeresolved then return -if SET(NO).TSize<=1 - return; -end; - -%Decrease one -SET(NO).CurrentTimeFrame = SET(NO).CurrentTimeFrame-1; -if SET(NO).CurrentTimeFrame<1 - SET(NO).CurrentTimeFrame = SET(NO).TSize; -end; - -%Calculate percentage -percent = (SET(NO).CurrentTimeFrame-1)/(SET(NO).TSize-1); -nos = unique(DATA.ViewPanels(DATA.ViewPanels > 0)); -%Loop over all image stacks to update time. -for loop=nos - SET(loop).CurrentTimeFrame = min(max(1,1+round(percent*(SET(loop).TSize-1))),SET(loop).TSize); -end; - -%Draw all panels -for no=nos([SET(nos).TSize]>1) - drawfunctions('updatenopanels',no); -end; - -updatevolume; -if DATA.Record - drawnow; - DATA.MovieFrame = mygetframe(DATA.imagefig); - export('exportmovierecorder_Callback','newframe'); -end; - -drawnow('expose');%Expose does not other callbacks to evaluate. - -%----------------------------------------------------- -function [xout,yout] = checkconsistencyhelper(xin,yin) -%----------------------------------------------------- -%Make sure that the contour is counter clock-wise and that it starts at -%three o clock. Also ensures that the points are evenly distributed. - -global DATA - -%--- Make sure evenly distributed -diffx = conv2(xin,[1;-1],'valid'); -diffy = conv2(yin,[1;-1],'valid'); -diffvec = sqrt(diffx.*diffx+diffy.*diffy); - -if any((diffvec-mean(diffvec))/mean(diffvec)>2) - %mydisp('Problem with endo => fixed, report to support'); -end; -contourlength = cumsum(diffvec); -xout = interp1(contourlength,xin(2:end),linspace(contourlength(1),contourlength(end),DATA.NumPoints-1)); -yout = interp1(contourlength,yin(2:end),linspace(contourlength(1),contourlength(end),DATA.NumPoints-1)); -xout(end+1) = xout(1); -yout(end+1) = yout(1); - -%--- Make sure correct rotation (starting pos) -xr = yout; -yr = xout; -mx = mean(xr); -my = mean(yr); - -if sum(unwrap(conv2(angle(complex(xr-mx,yr-my)),[1;-1],'valid')))<0 - disp(sprintf('counterclockwise endo %d slice %d',timeframe,zloop)); %#ok - xr = fliplr(xr); - yr = fliplr(yr); -end; - -[~,inda] = min(angle(complex(mx-xr,my-yr))); -xout(1:(DATA.NumPoints-inda+1)) = yr(inda:end); -yout(1:(DATA.NumPoints-inda+1)) = xr(inda:end); -xout((DATA.NumPoints+1-inda):end) = yr(1:inda); -yout((DATA.NumPoints+1-inda):end) = xr(1:inda); - -%-------------------------------------------- -function checkconsistency(timeframes,slice,no) -%--------------------------------------------- -%Check consistency, to prevent earlier -%manual segmentations that have problems with -%direction lef/right -global SET NO DATA - -if nargin==0 - timeframes=SET(NO).CurrentTimeFrame; %1; -end; - -if nargin<2 - slice=SET(NO).CurrentSlice; -end; - -if nargin<3 - no = NO; -end; +if nargin<3 + no = NO; +end if not(isempty(SET(no).EndoX)) && not(size(SET(no).EndoX,1)==DATA.NumPoints) - tempendox = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + tempendox = nan(DATA.NumPoints-1,SET(no).TSize,SET(no).ZSize); tempendoy = tempendox; timeframes = 1:SET(no).TSize; slice = 1:SET(no).ZSize; @@ -4512,11 +2546,11 @@ function checkconsistency(timeframes,slice,no) tempendox = []; % nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); tempendoy = []; % tempendox; else - tempendox = SET(no).EndoX; - tempendoy = SET(no).EndoY; + tempendox = SET(no).EndoX(1:end-1,:,:); + tempendoy = SET(no).EndoY(1:end-1,:,:); end if not(isempty(SET(no).EpiX)) && not(size(SET(no).EpiX,1)==DATA.NumPoints) - tempepix = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + tempepix = nan(DATA.NumPoints-1,SET(no).TSize,SET(no).ZSize); tempepiy = tempepix; timeframes = 1:SET(no).TSize; slice = 1:SET(no).ZSize; @@ -4524,11 +2558,11 @@ function checkconsistency(timeframes,slice,no) tempepix = []; % nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize);; tempepiy = []; % tempendox; else - tempepix = SET(no).EpiX; - tempepiy = SET(no).EpiY; + tempepix = SET(no).EpiX(1:end-1,:,:); + tempepiy = SET(no).EpiY(1:end-1,:,:); end if not(isempty(SET(no).RVEndoX)) && not(size(SET(no).RVEndoX,1)==DATA.NumPoints) - temprvendox = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + temprvendox = nan(DATA.NumPoints-1,SET(no).TSize,SET(no).ZSize); temprvendoy = tempendox; timeframes = 1:SET(no).TSize; slice = 1:SET(no).ZSize; @@ -4536,11 +2570,11 @@ function checkconsistency(timeframes,slice,no) temprvendox = []; % nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); temprvendoy = []; % tempendox; else - temprvendox = SET(no).RVEndoX; - temprvendoy = SET(no).RVEndoY; + temprvendox = SET(no).RVEndoX(1:end-1,:,:); + temprvendoy = SET(no).RVEndoY(1:end-1,:,:); end if not(isempty(SET(no).RVEpiX)) && not(size(SET(no).RVEpiX,1)==DATA.NumPoints) - temprvepix = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); + temprvepix = nan(DATA.NumPoints-1,SET(no).TSize,SET(no).ZSize); temprvepiy = tempendox; timeframes = 1:SET(no).TSize; slice = 1:SET(no).ZSize; @@ -4548,89 +2582,77 @@ function checkconsistency(timeframes,slice,no) temprvepix = []; % nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); temprvepiy = []; % tempendox; else - temprvepix = SET(no).RVEpiX; - temprvepiy = SET(no).RVEpiY; + temprvepix = SET(no).RVEpiX(1:end-1,:,:); + temprvepiy = SET(no).RVEpiY(1:end-1,:,:); end for timeframe = timeframes - for zloop=slice; + for zloop=slice %Endo if ~isempty(SET(no).EndoX) if not(isnan(SET(no).EndoX(1,timeframe,zloop))) %Call consistenyhelper - % try - [tempendox(:,timeframe,zloop),tempendoy(:,timeframe,zloop)] = checkconsistencyhelper(... - SET(no).EndoX(:,timeframe,zloop),... - SET(no).EndoY(:,timeframe,zloop)); - % catch - %small endo exists but to small to interpolate - % end - end; - end; + [tempendox(:,timeframe,zloop),tempendoy(:,timeframe,zloop)]=calcfunctions('resamplecurve',SET(no).EndoX(:,timeframe,zloop),SET(no).EndoY(:,timeframe,zloop),DATA.NumPoints-1); +% [tempendox(:,timeframe,zloop),tempendoy(:,timeframe,zloop)] = checkconsistencyhelper(... +% SET(no).EndoX(:,timeframe,zloop),... +% SET(no).EndoY(:,timeframe,zloop)); + end + end %Epi if ~isempty(SET(no).EpiX) if not(isnan(SET(no).EpiX(1,timeframe,zloop))) - %Call consistenyhelper - % try [tempepix(:,timeframe,zloop),tempepiy(:,timeframe,zloop)] = ... - checkconsistencyhelper(... - SET(no).EpiX(:,timeframe,zloop),... - SET(no).EpiY(:,timeframe,zloop)); - %catch - %small epi exists but to small to interpolate - %end - end; - end; + calcfunctions('resamplecurve',SET(no).EpiX(:,timeframe,zloop),SET(no).EpiY(:,timeframe,zloop),DATA.NumPoints-1); +% [tempepix(:,timeframe,zloop),tempepiy(:,timeframe,zloop)] = ... +% checkconsistencyhelper(... +% SET(no).EpiX(:,timeframe,zloop),... +% SET(no).EpiY(:,timeframe,zloop)); + end + end %RVEndo if ~isempty(SET(no).RVEndoX) if not(isnan(SET(no).RVEndoX(1,timeframe,zloop))) - %Call consistenyhelper - %try [temprvendox(:,timeframe,zloop),temprvendoy(:,timeframe,zloop)] = ... - checkconsistencyhelper(... - SET(no).RVEndoX(:,timeframe,zloop),... - SET(no).RVEndoY(:,timeframe,zloop)); - %catch - %small rvendo exists but to small to interpolate - %end - end; - end; + calcfunctions('resamplecurve',SET(no).RVEndoX(:,timeframe,zloop),SET(no).RVEndoY(:,timeframe,zloop),DATA.NumPoints-1); +% [temprvendox(:,timeframe,zloop),temprvendoy(:,timeframe,zloop)] = ... +% checkconsistencyhelper(... +% SET(no).RVEndoX(:,timeframe,zloop),... +% SET(no).RVEndoY(:,timeframe,zloop)); + end + end %RVEpi if ~isempty(SET(no).RVEpiX) if not(isnan(SET(no).RVEpiX(1,timeframe,zloop))) - %try %Call consistenyhelper [temprvepix(:,timeframe,zloop),temprvepiy(:,timeframe,zloop)] = ... - checkconsistencyhelper(... - SET(no).RVEpiX(:,timeframe,zloop),... - SET(no).RVEpiY(:,timeframe,zloop)); - %catch - %small rvepi exists but to small to interpolate - %end - end; - end; + calcfunctions('resamplecurve', SET(no).RVEpiX(:,timeframe,zloop),SET(no).RVEpiY(:,timeframe,zloop),DATA.NumPoints-1); +% checkconsistencyhelper(... +% SET(no).RVEpiX(:,timeframe,zloop),... +% SET(no).RVEpiY(:,timeframe,zloop)); + end + end - end; -end; + end +end if ~isempty(SET(no).EndoX) - SET(no).EndoX = tempendox; - SET(no).EndoY = tempendoy; + SET(no).EndoX = cat(1,tempendox,tempendox(1,:,:)); + SET(no).EndoY = cat(1,tempendoy,tempendoy(1,:,:)); end if ~isempty(SET(no).EpiX) - SET(no).EpiX = tempepix; - SET(no).EpiY = tempepiy; + SET(no).EpiX = cat(1,tempepix,tempepix(1,:,:)); + SET(no).EpiY = cat(1,tempepiy,tempepiy(1,:,:)); end if ~isempty(SET(no).RVEndoX) - SET(no).RVEndoX = temprvendox; - SET(no).RVEndoY = temprvendoy; + SET(no).RVEndoX = cat(1,temprvendox,temprvendox(1,:,:)); + SET(no).RVEndoY = cat(1,temprvendoy,temprvendoy(1,:,:)); end if ~isempty(SET(no).RVEpiX) - SET(no).RVEpiX = temprvepix; - SET(no).RVEpiY = temprvepiy; + SET(no).RVEpiX = cat(1,temprvepix,temprvepix(1,:,:)); + SET(no).RVEpiY = cat(1,temprvepiy,temprvepiy(1,:,:)); end %--------------------------------------- @@ -4644,7 +2666,7 @@ function checkconsistency(timeframes,slice,no) if any(isnan(x)) || any(isnan(y)) mask = false(outsize); return; -end; +end if not(DATA.Pref.IncludeAllPixelsInRoi) %mask = roipoly(repmat(uint8(0),outsize),y,x); @@ -4657,69 +2679,8 @@ function checkconsistency(timeframes,slice,no) y = interp1(y,linspace(1,length(y),1000)); mask(sub2ind(outsize,round(x),round(y))) = true; mask = imfill(mask,[mx my],4); -end; - -%------------------------------------------------------ -function z = reshape2layout(im,no,panel,outsideelement) -%------------------------------------------------------ -%Convert a 3D array to an layout:ed image with cols, and rows -global DATA SET NO - -if nargin<2 - no = NO; -end; - -if nargin<3 - panel = DATA.CurrentPanel; - if DATA.ViewPanels(panel) ~= no - panel = find(DATA.ViewPanels == no,1); - end end -if nargin<4 - outsideelement = 0; -end; - -z = repmat(outsideelement*im(1),DATA.ViewPanelsMatrix{panel}(1)*SET(no).XSize,DATA.ViewPanelsMatrix{panel}(2)*SET(no).YSize); -loop=1; -for slice=1:SET(no).ZSize - c = 1+mod(loop-1,DATA.ViewPanelsMatrix{panel}(2)); - r = ceil(loop/DATA.ViewPanelsMatrix{panel}(2)); - z(... - (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... - (1+(c-1)*SET(no).YSize):(c*SET(no).YSize)) = im(:,:,slice); - loop=loop+1; -end; - -%---------------------------------------- -function helpimagepos(im,sector,ofs,konst) %#ok -%---------------------------------------- -%helper function to display image. -global SET NO - -im = im(sector,:,:)-ofs; -im = squeeze(im); -im = im(:,2:end); -h = image(konst*im); -set(h,'xdata',SET(NO).TIncr*[0.5 SET(NO).TSize+0.5]); -set(gca,'yticklabel','','xlim',[0 (SET(NO).TSize-1)*SET(NO).TIncr]); -xlabel('Time'); -title(sprintf('Sector %d',sector)); - -%--------------------------------------- -function helpimageposneg(im,sector,konst) -%--------------------------------------- -%helper function to display image. -global SET NO - -im = im(sector,:,:); -im = squeeze(im); -im = im(:,2:end); -h = image(32+konst*im); -set(h,'xdata',SET(NO).TIncr*[0.5 SET(NO).TSize+0.5]); -set(gca,'yticklabel','','xlim',[0 (SET(NO).TSize-1)*SET(NO).TIncr]); -xlabel('Time'); -title(sprintf('Sector %d',sector)); %--------------------------- function resetlight_Callback %#ok @@ -4729,724 +2690,276 @@ function helpimageposneg(im,sector,konst) global DATA SET NO tools('enableundo',NO); -%set(DATA.Handles.resetlighticon,'state','off'); SET(NO).IntensityMapping.Contrast = 1; SET(NO).IntensityMapping.Brightness = 0.5; DATA.ViewIM{DATA.CurrentPanel} = []; -DATA.Overlay(DATA.CurrentPanel) = struct('alphadata',[],'cdata',[]); +if ~isempty(DATA.Overlay) + DATA.Overlay(DATA.CurrentPanel) = struct('alphadata',[],'cdata',[]); +end update_thumbnail(NO); -makeviewim(DATA.CurrentPanel,NO); -drawfunctions('drawcontrastimage',NO); %drawfunctions('drawsliceno',NO); +drawfunctions('drawno',NO) +createfunctions('addcolorbar',DATA.CurrentPanel) if DATA.Pref.UseLight DATA.BalloonLevel = -1; %Force update of ballonimage -end; +end %--------------------------- function resetlightall_Callback %#ok %--------------------------- %Activated by toolbar icon, different from contrast_Callback (below). -global DATA SET NO +global DATA SET for no = 1:length(SET) SET(no).IntensityMapping.Contrast = 1; SET(no).IntensityMapping.Brightness = 0.5; update_thumbnail(no); %drawfunctions('drawsliceno',NO); - end -DATA.ViewIM{DATA.CurrentPanel} = []; -DATA.Overlay(DATA.CurrentPanel) = struct('alphadata',[],'cdata',[]); -makeviewim(DATA.CurrentPanel,NO); -drawfunctions('drawcontrastimage',NO); + +for p = find(DATA.ViewPanels) + DATA.ViewIM{p} = []; + drawfunctions('drawimages',p); + createfunctions('addcolorbar',p) +end if DATA.Pref.UseLight DATA.BalloonLevel = -1; %Force update of ballonimage -end; +end + +%----------------------------------------------- +function [xlim,ylim] = getbox(no,destno,doindex) +%----------------------------------------------- +%find x-limits and y-limits for a zoom box + +global SET -%----------------------------------- -function contrast_Callback(arg,panel) -%----------------------------------- -%Activated by contrast tool, different from resetlight_Callback (above). +x=[]; +y=[]; -global DATA SET NO -persistent handles +%Source is destination. +if nargin == 1 + destno=no; +end + +if nargin <3 + doindex=0; +end +xsz = SET(destno).XSize; +ysz = SET(destno).YSize; + +diatype=1; +hasanyseg=0; +for type={'Endo','Epi','RVEndo','RVEpi'} + tmp_x = SET(no).([type{1},'X']); + tmp_y = SET(no).([type{1},'Y']); + if ~isempty(tmp_x) && ~all(isnan(tmp_x(:))) + hasanyseg=1; + x = [x;tmp_x(:)]; + y = [y;tmp_y(:)]; + if ~isempty(regexpi(type{1},'RV')) + diatype=2; + end + end +end -%if nargin==0 -% arg = 'init'; -%end; +if hasanyseg + %convert all segmentation rlapfh then get min max in destno + rlapfh=calcfunctions('xyz2rlapfh',no,x,y,ones(length(x),1)); + limits=calcfunctions('rlapfh2xyz',destno,rlapfh(:,1),rlapfh(:,2),rlapfh(:,3)); + dodia=1; +else + + diatype = 3; + %use auto crop tool + im = SET(no).IM; + roisizetime = 150; + roisizenotime = 200; + if SET(no).TSize>1 && SET(no).ZSize~=1 + roisize = roisizetime; + else + roisize = roisizenotime; + end + + nx = roisize/SET(no).ResolutionX; + ny = roisize/SET(no).ResolutionY; + [~,~,rlapfh] = autocrop(im,nx,ny,0,80,1,no); + if ~isempty(rlapfh) + limits = calcfunctions('rlapfh2xyz',destno,rlapfh(:,1),rlapfh(:,2),rlapfh(:,3)); + dodia=1; + else + xlim = [1,xsz]; + ylim = [1,ysz]; + return; + end +end -%switchtopanel(panel); +xmin = min(limits(1,:)); +ymin = min(limits(2,:)); +xmax = max(limits(1,:)); +ymax = max(limits(2,:)); -seltype = get(DATA.imagefig,'SelectionType'); -switch seltype - case 'alt' - DATA.contextmenu; - case {'normal','extend'} - switch arg -% case 'init' -% set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... -% sprintf('segment(''contrast_Callback'',''down'',%d)',panel)); -% %SET(NO).IntensityMapping.Contrast = 1; %Default values -% %SET(NO).IntensityMapping.Brightness = 0.5; %Default values -% %SET(NO).IntensityMapping.Compression = []; - case 'down' - switchtopanel(panel); - tools('enableundo',NO); - h = DATA.Handles.imageaxes(panel); - [x,y] = mygetcurrentpoint(h); - handles.xstart = x; - handles.ystart = y; - handles.xsize = get(h,'xlim'); - handles.xsize = handles.xsize(end)-handles.xsize(1); - handles.ysize = get(h,'ylim'); - handles.ysize = handles.ysize(end)-handles.ysize(1); - handles.deltacontrast = 0; - handles.deltabrightness = 0; - - switch seltype - case 'normal' - %Button down, intialize - set(gcf,'WindowButtonMotionFcn','segment(''contrast_Callback'',''motion'')'); - set(gcf,'WindowButtonUpFcn','segment(''contrast_Callback'',''up'')'); - handles.im = cell(1,numel(DATA.ViewPanels)); - switch DATA.ViewPanelsType{DATA.CurrentPanel} - case {'one','ortho'} - im = SET(NO).IM(:,:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); - case {'montage','montagerow','montagefit','sax3'} - %Create space - im = reshape2layout(... - squeeze(SET(NO).IM(:,:,SET(NO).CurrentTimeFrame,:))); - end; - handles.im{DATA.CurrentPanel} = im; %single(im); -% %hide colormap until button up -% disp('hej1'); -% handles.stateandiconcolorbar = segment('iconson','colorbar'); -% if handles.stateandiconcolorbar{1} -% DATA.GUISettings.ShowColorbar = false; -% drawfunctions('drawcolorbar'); -% end - case 'extend' - %Button down, intialize - set(gcf,'WindowButtonMotionFcn','segment(''contrast_Callback'',''motionall'')'); - set(gcf,'WindowButtonUpFcn','segment(''contrast_Callback'',''upall'')'); - handles.im = cell(1,numel(DATA.ViewPanels)); - for i = 1:numel(DATA.ViewPanels) - no = DATA.ViewPanels(i); - if no > 0 - switch DATA.ViewPanelsType{i} - case {'one','ortho'} - im = SET(no).IM(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - case {'montage','montagerow','montagefit','sax3'} - %Create space - im = reshape2layout(... - squeeze(SET(no).IM(:,:,SET(no).CurrentTimeFrame,:)),no,i); - end; - handles.im{i} = im; %single(im); - end - end -% %hide colormap until button up -% disp('hej2'); -% handles.stateandiconcolorbar = segment('iconson','colorbar'); -% if handles.stateandiconcolorbar{1} -% DATA.GUISettings.ShowColorbar = false; -% drawfunctions('drawcolorbar'); -% end - end - case {'up','upall'} - panels = DATA.CurrentPanel; - if strcmp(arg,'upall') - panels = 1:numel(DATA.ViewPanels); - panels = panels(DATA.ViewPanels > 0); - end - %restore -% %show colormap again if it was shown before contrast setting -% if handles.stateandiconcolorbar{1} -% DATA.GUISettings.ShowColorbar = true; -% end - set(gcf,'WindowButtonMotionFcn',''); - set(gcf,'WindowButtonUpFcn','segment(''buttonup_Callback'')'); - precontrast = SET(NO).IntensityMapping.Contrast; - prebrightness = SET(NO).IntensityMapping.Brightness; - for panel = panels - no = DATA.ViewPanels(panel); - if ~isempty(SET(no).IntensityScaling) && ~isempty(SET(no).IntensityMapping) - [window,level] = calcfunctions('con2win',... - precontrast+handles.deltacontrast,... - prebrightness+handles.deltabrightness,NO); - [contrast,brightness] = calcfunctions('win2con',window,level,no); - else - contrast = precontrast+handles.deltacontrast; - brightness = prebrightness+handles.deltabrightness; - end - SET(no).IntensityMapping.Contrast = contrast; - SET(no).IntensityMapping.Brightness = brightness; - DATA.ViewIM{panel} = []; - DATA.Overlay(panel) = struct('alphadata',[],'cdata',[]); - makeviewim(panel,no); - end - for no = DATA.ViewPanels(panels); - drawfunctions('updatenopanels',no); - update_thumbnail(no); - end - if DATA.Pref.UseLight - DATA.BalloonLevel = -1; %Force update of ballonimage - end; - case 'wheelUpBrightness' %Brightness only - SET(NO).IntensityMapping.Brightness = SET(NO).IntensityMapping.Brightness+0.1; - DATA.ViewIM{DATA.CurrentPanel} = []; - DATA.Overlay(DATA.CurrentPanel) = struct('alphadata',[],'cdata',[]); - makeviewim(DATA.CurrentPanel,NO); - drawfunctions('updatenopanels',NO); - update_thumbnail(NO); - if DATA.Pref.UseLight - DATA.BalloonLevel = -1; %Force update of ballonimage - end; - case 'wheelDownBrightness' %Brightness only - SET(NO).IntensityMapping.Brightness = SET(NO).IntensityMapping.Brightness-0.1; - DATA.ViewIM{DATA.CurrentPanel} = []; - DATA.Overlay(DATA.CurrentPanel) = struct('alphadata',[],'cdata',[]); - makeviewim(DATA.CurrentPanel,NO); - drawfunctions('updatenopanels',NO); - update_thumbnail(NO); - if DATA.Pref.UseLight - DATA.BalloonLevel = -1; %Force update of ballonimage - end; - case {'motion','motionall'} - panels = DATA.CurrentPanel; - if strcmp(arg,'motionall') - panels = 1:numel(DATA.ViewPanels); - panels = panels(DATA.ViewPanels > 0); - end - h = DATA.Handles.imageaxes(DATA.CurrentPanel); - [x,y] = mygetcurrentpoint(h); - handles.deltacontrast = (x-handles.xstart)/handles.xsize; - handles.deltabrightness = (handles.ystart-y)/handles.ysize; - for panel = panels - no = DATA.ViewPanels(panel); - if ~isempty(SET(no).IntensityScaling) && ~isempty(SET(no).IntensityMapping) -% [window,level] = calcfunctions('con2win',... -% SET(NO).IntensityMapping.Contrast+handles.deltacontrast,... -% SET(NO).IntensityMapping.Brightness+handles.deltabrightness,NO); - [window,level] = calcfunctions('con2win',... - SET(no).IntensityMapping.Contrast+handles.deltacontrast,... - SET(no).IntensityMapping.Brightness+handles.deltabrightness,no); - [contrast,brightness] = calcfunctions('win2con',window,level,no); - else - %contrast = SET(NO).IntensityMapping.Contrast+handles.deltacontrast; - %brightness = SET(NO).IntensityMapping.Brightness+handles.deltabrightness; - contrast = SET(no).IntensityMapping.Contrast+handles.deltacontrast; - brightness = SET(no).IntensityMapping.Brightness+handles.deltabrightness; - - end - im = calcfunctions('remapuint8',handles.im{panel},no,... - calcfunctions('returnmapping',no),contrast,brightness); - set(DATA.Handles.imagehandle(panel),'cdata',im); - end +if xmax-xmin<20 + xmax=xsz; + xmin=1; + dodia=0; +end - otherwise - myfailed('Unknown option to contrast Callback',DATA.GUI.Segment); - end; -end; - +if ymax-ymin<20 + ymax=ysz; + ymin=1; + dodia=0; +end -%---------------------------- -function [xlim,ylim] = getbox(no,destno,doindex) -%------------------------ -%find x-limits and y-limits for a zoom box +if dodia + switch diatype + case 1 + dia = norm([xmax,ymax]-[xmin,ymin])/2*0.8; + case 2 %there is RV do very little margin addition + dia = norm([xmax,ymax]-[xmin,ymin])/2*0.2; + case 3 %from autocrop do "lagom" margin. + dia = norm([xmax,ymax]-[xmin,ymin])/2*0.4; + end +else + dia=0; +end +xlim = [xmin-dia,xmax+dia]; +ylim = [ymin-dia,ymax+dia]; -global SET +if doindex + xlim = round(xlim); + ylim = round(ylim); + xlim(xlim>xsz) = xsz; + ylim(ylim>ysz) = ysz; + xlim(xlim<1) = 1; + ylim(ylim<1) = 1; +end - x=[]; - y=[]; - - - %Source is destination. - if nargin == 1 - destno=no; - end - - if nargin <3 - doindex=0; +%---------------- +function autozoom %#ok +%---------------- +%New autozoom autozooms everything that is displayed. + +global DATA SET + +panel = DATA.CurrentPanel; +panels = DATA.ViewPanels; +no = panels(panel); +origno = no; +zdirno = cross(SET(no).ImageOrientation(1:3),SET(no).ImageOrientation(4:6)); + +%Check which nos to do +nos = no; +for loop = 1:length(SET) + + loopno = loop; + if ~isequal(loopno,0) + zdir = cross(SET(loopno).ImageOrientation(1:3),SET(loopno).ImageOrientation(4:6)); + a = acos(abs(sum(zdir.*zdirno)))/pi*180; + if a<20 + nos = [nos loopno]; + end end - xsz = SET(destno).XSize; - ysz = SET(destno).YSize; - - diatype=1; - hasanyseg=0; +end + +%remove duplicates +nos = union(nos,[]); + +%Loop over to find contours +hasanyseg = false; +hasrv = false; +x = []; +y = []; + +for loop = 1:length(nos) + no = nos(loop); for type={'Endo','Epi','RVEndo','RVEpi'} tmp_x = SET(no).([type{1},'X']); - tmp_y = SET(no).([type{1},'Y']); + tmp_y = SET(no).([type{1},'Y']); if ~isempty(tmp_x) && ~all(isnan(tmp_x(:))) - hasanyseg=1; - x=[x;tmp_x(:)]; - y=[y;tmp_y(:)]; + hasanyseg = true; + tmp_x = tmp_x(~isnan(tmp_x(:))); + tmp_y = tmp_y(~isnan(tmp_y(:))); + + %Convert to origno's coordinate system + pos = calcfunctions('xyz2rlapfh',no,tmp_x,tmp_y,repmat(SET(no).ZSize/2,size(tmp_x))); + pos = calcfunctions('rlapfh2xyz',origno,pos(:,1),pos(:,2),pos(:,3)); + + x = [x;pos(1,:)']; + y = [y;pos(2,:)']; if ~isempty(regexpi(type{1},'RV')) - diatype=2; + hasrv = true; end end end +end - if hasanyseg - %convert all segmentation rlapfh then get min max in destno - rlapfh=calcfunctions('xyz2rlapfh',no,x,y,ones(length(x),1)); - limits=calcfunctions('rlapfh2xyz',destno,rlapfh(:,1),rlapfh(:,2),rlapfh(:,3)); - dodia=1; - else - - diatype = 3; - %use auto crop tool - im= SET(no).IM; - roisizetime=150; - roisizenotime=200; - if SET(no).TSize>1 && SET(no).ZSize~=1 - roisize = roisizetime; - else - roisize = roisizenotime; - end; +if hasrv + fmargin = 1.15; +else + fmargin = 1.5; +end + +if ~hasanyseg + return; +end + +%Compute limit & center (in origno coordinate system) +xmin = min(x); +xmax = max(x); +ymin = min(y); +ymax = max(y); +xc = mean(x); +yc = mean(y); + +%Loop over panels and check if update +for loop = 1:length(panels) + + panel = loop; + no = panels(loop); + + if ismember(no,nos) && isequal(DATA.ViewPanelsType{panel},'one') + + %get previous zoomstate + zoomstate = viewfunctions('getnewzoomstate',panel,no); - nx = roisize/SET(no).ResolutionX; - ny = roisize/SET(no).ResolutionY; - [~,~,rlapfh] = autocrop(im,nx,ny,0,80,1,no); - if ~isempty(rlapfh) - limits = calcfunctions('rlapfh2xyz',destno,rlapfh(:,1),rlapfh(:,2),rlapfh(:,3)); - dodia=1; - else - xlim=[1,xsz]; - ylim=[1,ysz]; - return; - end - end - xmin=min(limits(1,:)); - ymin=min(limits(2,:)); - xmax=max(limits(1,:)); - ymax=max(limits(2,:)); + %Convert xc,yc + pos = calcfunctions('xyz2rlapfh',origno,[xc;xmin;xmax],[yc;ymin;ymax],repmat(SET(origno).ZSize/2,3,1)); + pos = calcfunctions('rlapfh2xyz',no,pos(:,1),pos(:,2),pos(:,3)); + xcno = pos(1,1); ycno = pos(2,1); + xminno = pos(1,2); yminno = pos(2,2); + xmaxno = pos(1,3); ymaxno = pos(2,3); - + oldxrange = zoomstate(4)-zoomstate(3); + oldyrange = zoomstate(2)-zoomstate(1); + oldxc = mean(zoomstate(3:4)); + oldyc = mean(zoomstate(1:2)); + translatex = oldxc-xcno; + translatey = oldyc-ycno; - if xmax-xmin<20 - xmax=xsz; - xmin=1; - dodia=0; - end + %Translate + oldxc = oldxc-translatex; + oldyc = oldyc-translatey; - if ymax-ymin<20 - ymax=ysz; - ymin=1; - dodia=0; - end + %Find out zoom + fx = max((oldxc-xminno)/(oldxrange/2),(xmaxno-oldxc)/(oldxrange/2)); + fy = max((oldyc-yminno)/(oldyrange/2),(ymaxno-oldyc)/(oldyrange/2)); + f = max(fx,fy)*fmargin; - if dodia - switch diatype - case 1 - dia=norm([xmax,ymax]-[xmin,ymin])/2*0.8; - case 2 %there is RV do very little margin addition - dia=norm([xmax,ymax]-[xmin,ymin])/2*0.2; - case 3 %from autocrop do "lagom" margin. - dia=norm([xmax,ymax]-[xmin,ymin])/2*0.4; - end - else - dia=0; - end - xlim=[xmin-dia,xmax+dia]; - ylim=[ymin-dia,ymax+dia]; + newzoomstate = [oldyc-oldyrange/2*f oldyc+oldyrange/2*f oldxc-oldxrange/2*f oldxc+oldxrange/2*f]; + SET(no).NormalZoomState = newzoomstate; - if doindex - xlim=round(xlim); - ylim=round(ylim); - xlim(xlim>xsz)=xsz; - ylim(ylim>ysz)=ysz; - xlim(xlim<1)=1; - ylim(ylim<1)=1; - end - -% if isempty(xlim) -% xmin=1; -% xmax=xsz; -% else -% xmin=xlim(1); -% xmax=xlim(end); -% end -% -% if isempty(ylim) -% ymin=1; -% ymax=ysz; -% else -% ymin=ylim(1); -% ymax=ylim(end); -% end + %update it graphically + viewfunctions('updatezoomandaspectratio',panel); - + %we want to update the text position and the frame + viewfunctions('updatetextposition',panel) + + end -% %-------------------- -% function varargout = getbox(no,tono,indexes) -% %----------------- -% global SET -% -% if nargin<3 -% indexes=0; -% end -% xsz=SET(no).XSize; -% ysz=SET(no).YSize; -% -% hasanyseg=0; -% for type={'Endo','Epi','RVEndo','RVEpi'} -% x=SET(no).([type{1},'X']); -% if ~isempty(x) && ~all(isnan(x(:))) -% hasanyseg=1; -% break -% end -% end -% -% if hasanyseg -% xmin=[]; -% ymin=[]; -% xmax=[]; -% ymax=[]; -% for type={'Endo','Epi','RVEndo','RVEpi'} -% -% x = SET(no).([type{1},'X']); -% y = SET(no).([type{1},'Y']); -% -% xmin = min([xmin floor(min(x(:)))]); -% ymin = min([ymin floor(min(y(:)))]); -% xmax = max([xmax ceil(max(x(:)))]); -% ymax = max([ymax ceil(max(y(:)))]); -% -% dodia = 1;%round(norm([xmax,ymax]-[xmin,ymin])/2*0.8); -% -% if xmin<1 -% xmin=1; -% dodia=0; -% end -% -% if ymin<1 -% ymin=1; -% dodia=0; -% end -% -% if xmax>xsz -% xmax=xsz; -% dodia=0; -% end -% -% if ymax>ysz -% ymax=ysz; -% dodia=0; -% end -% -% %this catches segmentation blow ups -% if ymax-ymin<20 -% ymin=1; -% ymax=ysz; -% dodia=0; -% end -% -% if xmax-xmin<20 -% xmin=1; -% xmax=xsz; -% dodia=0; -% end -% -% end -% -% else -% if nargin == 2 -% no=tono; -% xsz=SET(no).XSize; -% ysz=SET(no).YSize; -% end -% -% im= SET(no).IM; -% roisizetime=150; -% roisizenotime=200; -% if SET(no).TSize>1 && SET(no).ZSize~=1 -% roisize = roisizetime; -% else -% roisize = roisizenotime; -% end; -% -% nx = roisize/SET(no).ResolutionX; -% ny = roisize/SET(no).ResolutionY; -% [xlim,ylim,rlapfh] = autocrop(im,nx,ny,0,128,1,no); -% dodia=0; -% -% if isempty(xlim) -% xmin=1; -% xmax=xsz; -% else -% xmin=xlim(1); -% xmax=xlim(end); -% end -% -% if isempty(ylim) -% ymin=1; -% ymax=ysz; -% else -% ymin=ylim(1); -% ymax=ylim(end); -% end -% end -% % xlim=[xmin-dia,xmax+dia]; -% % ylim=[ymin-dia,ymax+dia]; -% xlim=[xmin,xmax]; -% ylim=[ymin,ymax]; -% %SET(no).NormalZoomState=[ymin-dia,ymax+dia,xmin-dia,xmax+dia]; -% -% rlapfh = calcfunctions('xyz2rlapfh',no,xlim',ylim',[1,1]'); -% -% if nargin ==1 && nargout>1 -% if dodia -% dia=norm([xlim(end),ylim(end)]-[xlim(1),ylim(1)])/2*0.8; -% else -% dia=0; -% end -% xlim=[xlim(1)-dia,xlim(end)+dia]; -% ylim=[ylim(1)-dia,ylim(end)+dia]; -% -% if indexes -% xlim(xlim<1)=1; -% ylim(ylim<1)=1; -% -% xlim(xlim>SET(no).XSize)=SET(no).XSize; -% ylim(ylim>SET(no).YSize)=SET(no).YSize; -% end -% end -% -% if nargin>1 && nargout>1 -% limits = calcfunctions('rlapfh2xyz',tono,rlapfh(:,1),rlapfh(:,2),rlapfh(:,3)); -% -% %sortlimits -% xlim=sort(limits(1,:),'ascend'); -% ylim=sort(limits(2,:),'ascend'); -% -% if dodia -% dia=norm([xlim(end),ylim(end)]-[xlim(1),ylim(1)])/2*0.8; -% else -% dia=0; -% end -% xlim=[xlim(1)-dia,xlim(end)+dia]; -% ylim=[ylim(1)-dia,ylim(end)+dia]; -% -% -% if indexes -% xlim(xlim<1)=1; -% ylim(ylim<1)=1; -% -% xlim(xlim>SET(tono).XSize)=SET(tono).XSize; -% ylim(ylim>SET(tono).YSize)=SET(tono).YSize; -% end -% end -% -% if nargout==1 -% varargout={rlapfh}; -% end -% -% if nargout==2 -% varargout={round(xlim),round(ylim)}; -% end -% -% if nargout==3 -% varargout={rlapfh,round(xlim),round(ylim)}; -% end - - -%------------------------- - function varargout = autozoom -%------------------------- -% Autozooms everything that is displayed. -global DATA SET - -% if isempty(DATA.ZoomState) || DATA.ZoomState == 0 -% DATA.ZoomState = 1; -% elseif DATA.ZoomState==2 -% DATA.ZoomState=0; -% end - -no_inds=find(DATA.ViewPanels~=0); -no_inds(~strcmp('one',DATA.ViewPanelsType(no_inds)))=[]; - -lvno = findfunctions('findcineshortaxisno'); - -if ~isempty(lvno) -imageorientation = SET(lvno).ImageOrientation; -refaxis = cross(imageorientation(1:3),imageorientation(4:6)); -tol=11; -fixednos = false(size(no_inds)); - -for i=1:length(no_inds) - no=DATA.ViewPanels(no_inds(i)); - hasanyseg=0; - for type={'Endo','Epi','RVEndo','RVEpi'} - x=SET(no).([type{1},'X']); - if ~isempty(x) && ~all(isnan(x(:))) - hasanyseg=1; - break - end - end - - if hasanyseg && no~=lvno - break - end - - imageorientation = SET(no).ImageOrientation; - axis = cross(imageorientation(1:3),imageorientation(4:6)); - score = abs(sum(refaxis.*axis)); %scalar product, and abs - if acos(score)*180/pixsz -% xmax=xsz; -% dia=0; -% end -% -% if ymax>ysz -% ymax=ysz; -% dia=0; -% end -% -% %this catches segmentation blow ups -% if ymax-ymin<20 -% ymin=1; -% ymax=ysz; -% dia=0; -% end -% -% if xmax-xmin<20 -% xmin=1; -% xmax=xsz; -% dia=0; -% end -% -% end -% -% else -% im= SET(no).IM; -% roisizestacks=200; -% roisizeslices=250; -% if SET(no).ZSize>1 -% roisize = roisizestacks; -% else -% roisize = roisizeslices; -% end; -% -% nx = roisize/SET(no).ResolutionX; -% ny = roisize/SET(no).ResolutionY; -% [xlim,ylim,varargout{1}] = autocrop(im,nx,ny,0,128,13,no); -% dia=0; -% -% if isempty(xlim) -% xmin=1; -% xmax=xsz; -% else -% xmin=xlim(1); -% xmax=xlim(end); -% end -% -% if isempty(ylim) -% ymin=1; -% ymax=ysz; -% else -% ymin=ylim(1); -% ymax=ylim(end); -% end -% end -% SET(no).NormalZoomState=[ymin-dia,ymax+dia,xmin-dia,xmax+dia]; -% set(DATA.Handles.imageaxes(i),'xlim',[ymin-dia,ymax+dia],'ylim',[xmin-dia,xmax+dia]) -% -% drawfunctions('viewupdatetextposition',i); -% drawfunctions('viewupdateannotext',i); -%end - - - - -% Plan B -% if ymax-ymin>=xmax-xmin -% f = 120/(ymax-ymin+1); -% else -% f = 120/(xmax-xmin+1); -% end -% -% zoomhelper(no,f); -%end +drawfunctions('drawselectedframe',DATA.CurrentPanel); %------------------------------ function autocontrastall_Callback %#ok @@ -5459,8 +2972,9 @@ function contrast_Callback(arg,panel) end for panelloop = 1:length(DATA.ViewPanels) - panel = DATA.ViewPanels(panelloop); - drawfunctions('drawcontrastimage',panel); + %panel = DATA.ViewPanels(panelloop); + DATA.ViewIM{panelloop} = []; + drawfunctions('drawimages',panelloop); end %------------------------------ @@ -5468,14 +2982,15 @@ function contrast_Callback(arg,panel) %------------------------------ %Automatically calculates contrast settings. global NO - -autocontrast(NO); +no = NO; +autocontrast(no); +segment('update_thumbnail',no) %------------------------- function autocontrast(no,silent) %------------------------- %Helper functionk to autocontrast_Callback_ -global SET +global SET DATA if nargin <2 silent=0; @@ -5515,26 +3030,16 @@ function autocontrast(no,silent) SET(no).IntensityMapping.Brightness=brightness; %update image -if ~silent - drawfunctions('drawcontrastimage',no); +for p = find(DATA.ViewPanels==no) + DATA.ViewIM{p} = []; + drawfunctions('drawimages',p) + createfunctions('addcolorbar',p) end +% if ~silent +% drawfunctions('drawcontrastimage',no); +% end myworkoff; -%---------------------------------------- -function placetimeresolvedpoints_Callback %#ok -%---------------------------------------- -%When this option is enabled then points are placed timeresolved -%and the name is re-used. - -global DATA - -%Updating in menu. When checked it changes how points are placed. -if isequal(get(DATA.Handles.placetimeresolvedpoints,'checked'),'off') - set(DATA.Handles.placetimeresolvedpoints,'checked','on'); -else - set(DATA.Handles.placetimeresolvedpoints,'checked','off'); -end; - %----------------------------------- function measuremove_Callback(dx,dy) %#ok %----------------------------------- @@ -5545,19 +3050,19 @@ function measuremove_Callback(dx,dy) %#ok no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; -end; +end n = DATA.MeasureN; if (length(SET(no).Measure) @@ -5569,7 +3074,7 @@ function measuremove_Callback(dx,dy) %#ok no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; -end; +end if ~isempty(SET(no).Measure) stri = []; @@ -5582,13 +3087,13 @@ function measuremove_Callback(dx,dy) %#ok sprintf('%s\t%f\n',... SET(no).Measure(loop).Name,... SET(no).Measure(loop).Length)]; %#ok - end; + end clipboard('copy',stri); mymsgbox('Results copied to clipboard','Done!',DATA.GUI.Segment); else myfailed('Nothing to export.',DATA.GUI.Segment); -end; +end %----------------------------------- function measureshapeexport_Callback %#ok @@ -5599,7 +3104,7 @@ function measuremove_Callback(dx,dy) %#ok no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; -end; +end if ~isempty(SET(no).Measure) c = cell(6,3*numel(SET(no).Measure)); @@ -5620,4722 +3125,250 @@ function measuremove_Callback(dx,dy) %#ok [SET(no).Measure(mnbr).Y]*SET(no).ResolutionY-basepoint(2)); c(5:4+numel(SET(no).Measure(mnbr).X),mnbr*3) = num2cell( ... -[SET(no).Measure(mnbr).Z]*(SET(no).SliceGap + SET(no).SliceThickness)-basepoint(3)); -% stri = [sprintf('PatientName:\t%s\n',SET(no).PatientInfo.Name) ... -% sprintf('Name\t%s\nLength[mm]\t%f\nX\tY\tZ\n',SET(no).Measure(mnbr).LongName,... -% SET(no).Measure(mnbr).Length)]; -% basepoint = [SET(no).Measure(mnbr).X(1)*SET(no).ResolutionX, ... -% SET(no).Measure(mnbr).Y(1)*SET(no).ResolutionY, ... -% -SET(no).Measure(mnbr).Z(1)*(SET(no).SliceGap + SET(no).SliceThickness)]; -% for loop=1:length(SET(no).Measure(mnbr).X) -% stri = [stri sprintf('%f\t%f\t%f\n', ... -% SET(no).Measure(mnbr).X(loop)*SET(no).ResolutionX-basepoint(1), ... -% SET(no).Measure(mnbr).Y(loop)*SET(no).ResolutionY-basepoint(2), ... -% -SET(no).Measure(mnbr).Z(loop)* ... -% (SET(no).SliceGap + SET(no).SliceThickness)- basepoint(3))]; %#ok end cell2clipboard(c); else myfailed('Nothing to export.',DATA.GUI.Segment); -end; - -%-------------------------------------- -function measurepoint_Buttondown(panel) %#ok -%-------------------------------------- -%Buttondown function when clicking on a measurement point/marker. -global DATA SET NO - -killbuttondown = switchtopanel(panel); - -if killbuttondown - return end -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -if not(isfield(SET(no),'Measure')) - SET(no).Measure = []; -end; -%Get clicked coordinate -[x,y,slice] = getclickedcoords; -% If slice has changed, make sure montage/one are in sync -% if (slice>SET(no).ZSize) -% %return; -% end -if ~ismember(DATA.ViewPanelsType{panel},{'hla','vla','gla'}) - switchtoslice(slice); -end -type = get(DATA.imagefig,'SelectionType'); - -%Find correct point -ind = NaN; -mindist = 1e10; -[measure, slice] = segment('getmeasurecoords',no,panel); - -%Find closest point: -for loop=1:length(measure) - if slice<=max(measure(loop).Z) && slice>=min(measure(loop).Z) - [dist,num] = min(sqrt(... - (measure(loop).X-y).^2+... - (measure(loop).Y-x).^2)); - - if dist SBT20160308 -%---------------------- -%Motion function for measurements. -persistent startx starty startslice -global DATA SET NO +% Get open SETs panels but exclude no +openpanels = DATA.ViewPanels; +openpanels = unique(openpanels); +openpanels = openpanels(openpanels~=no&openpanels~=0); -if (nargin==1) - %Reset coordinates - [startx,starty,startslice] = getclickedcoords; +% Find SETs that are parallel to SET(no), but not a linked flow. +if ~isempty(SET(no).Flow) + flownos = [... + SET(no).Flow.MagnitudeNo ... + SET(no).Flow.PhaseNo ... + SET(no).Flow.PhaseX ... + SET(no).Flow.PhaseY ... + SET(no).Flow.Angio ... + SET(no).Flow.VelMag]; else - no = NO; - if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; - end; - - %Compute translational difference: - [x,y,slice] = getclickedcoords; - - %Abort upon slice-change: - if (slice~=startslice) - DATA.measure_Buttonup - return; - end - - % Only update if marker is inside image: - if (x>0.5) && (y>0.5) && (x -%---------------------- -%Motion function for measurements. -global DATA SET NO - -if nargin < 1 - ind = numel(DATA.MeasureX); + flownos = []; end - -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -[x,y,slice] = getclickedcoords; - -% first line is for montage -% second line is for one-view. -if (x>0.5) && (y>0.5) && (x end - -end - -%--------------------------------- -function measure_Buttondown(panel) %#ok -%--------------------------------- -%Button down function for placing measurements. -global DATA SET NO - -killbuttondown = switchtopanel(panel); - -if killbuttondown - return end -if DATA.Interactionlock - return; -end; - -seltype = get(DATA.imagefig,'SelectionType'); -switch seltype - case {'normal','extend'} - - %Use to point to mag data set - no = NO; - if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; - end; - - [x,y,slice] = getclickedcoords; - if ismember(DATA.ViewPanelsType{panel},{'montage','montagerow','montagefit'}) - % If slice has changed, make sure montage/one are in sync - if (slice>SET(no).ZSize) - % ~(strcmp(DATA.ViewPanelsType{panel},'hla') && slice <= SET(no).HLA.maxslice || ... - % strcmp(DATA.ViewPanelsType{panel},'vla') && slice <= SET(no).VLA.maxslice) - return; - end - switchtoslice(slice); - end +if not(isempty(parallel)) + % Calculate new CurrentSlide for parallel SETs + %viewdir = cross(SET(no).ImageOrientation(1:3),SET(no).ImageOrientation(4:6))'; + %currzdist = (SET(no).CurrentSlice-1)*(SET(no).SliceThickness+SET(no).SliceGap); + pos = calcfunctions('xyz2rlapfh',no,SET(no).XSize/2,SET(no).YSize/2,SET(no).CurrentSlice); %Center of image and current slice + for i = 1:length(parallel) - DATA.MeasureT = SET(NO).CurrentTimeFrame; - DATA.MeasureN = length(SET(no).Measure)+1; - DATA.MeasureName = ''; + %--- Old code + % Calculate closest slice in parallel SETs and change their + % CurrentSlice + %slicethickness = SET(parallel(i)).SliceThickness + SET(parallel(i)).SliceGap; + %zdistances = 0:slicethickness:(slicethickness * (SET(parallel(i)).ZSize-1)); + %zdiff = SET(parallel(i)).ImagePosition - SET(no).ImagePosition; + %zdiff = dot(zdiff,viewdir); + %zdistances = zdistances - zdiff; + %[~,slice] = min(abs(zdistances - currzdist)); + - if strcmp(DATA.ViewPanelsType{panel},'mmodetemporal') - myfailed('Can not measure in time.',DATA.GUI.Segment); - return - end - [DATA.MeasureOffsetY,DATA.MeasureOffsetX] = calcfunctions('calcoffset',slice,[],no,panel); + %--- New code + [outpos] = calcfunctions('rlapfh2xyz',parallel(i),pos(1),pos(2),pos(3)); + slice = min(max(1,round(outpos(3))),SET(parallel(i)).ZSize); - set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''measure_Motion'');',mfilename)); - if strcmp(seltype,'normal') - DATA.MeasureX = [y;y]; - DATA.MeasureY = [x;x]; - DATA.MeasureZ = [slice;slice]; - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''measure_Buttonup'')','segment')); - else - DATA.MeasureX = y; - DATA.MeasureY = x; - DATA.MeasureZ = slice; - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''measureput_Buttonup'')',mfilename)); - end + %--- Store + SET(parallel(i)).CurrentSlice = slice; + SET(parallel(i)).StartSlice = slice; + SET(parallel(i)).EndSlice = slice; - hold(DATA.Handles.imageaxes(DATA.CurrentPanel),'on'); - DATA.Handles.measureline{DATA.CurrentPanel}{DATA.MeasureN} = plot(... - DATA.Handles.imageaxes(DATA.CurrentPanel),DATA.MeasureY,DATA.MeasureX,... - 'Color',DATA.GUISettings.MeasureLineSpec{1},... - 'Marker', DATA.GUISettings.MeasureLineSpec{2},... - 'LineStyle',DATA.GUISettings.MeasureLineSpec{3},... - 'linewidth',DATA.GUISettings.MeasureLineSpec{4},... - 'markersize',DATA.GUISettings.MeasureLineMarkerSize); - DATA.Handles.measuretext{DATA.CurrentPanel}(DATA.MeasureN) = text(... - mean(DATA.MeasureY),mean(DATA.MeasureX),'', ... - 'Parent',DATA.Handles.imageaxes(DATA.CurrentPanel)); - hold(DATA.Handles.imageaxes(DATA.CurrentPanel),'off'); - case 'alt' - DATA.contextmenu; + end end -%--------------------------- -function measureput_Buttonup %#ok -%--------------------------- -%Called when a measurement point (except the endpoint) is placed -global DATA - -switch get(DATA.imagefig,'SelectionType') - case 'extend' - DATA.MeasureX(end+1,1) = DATA.MeasureX(end); - DATA.MeasureY(end+1,1) = DATA.MeasureY(end); - DATA.MeasureZ(end+1,1) = DATA.MeasureZ(end); - case 'normal' - DATA.measure_Buttonup; +if nargout == 1 + parallelout = parallel; end +%----------------------------- + function do = doatrialscar(no) +%----------------------------- +%Helper function to check if user input is for atrial scar or lv scar +%(default) -%-------------------------------- -function normal_Buttondown(panel) %#ok -%-------------------------------- -%Called when button down in normal view -global DATA SET +global SET -switchtopanel(panel); +do = false; -if DATA.Interactionlock +if isempty(SET(no).RVEndoX) return; -end; - -switch get(DATA.imagefig,'SelectionType') - case 'extend' %shift - %pan_Buttondown - contrast_Callback('down',panel) - case 'alt' - DATA.contextmenu; - case 'open' - %Double click - no = DATA.ViewPanels(DATA.CurrentPanel); - if numel(DATA.ViewPanels) > 1 - if strcmp(DATA.ViewPanelsType(1),'ortho') - DATA.LastView = []; - else - DATA.LastView = struct(... - 'Panels',DATA.ViewPanels, ... - 'PanelsType',{DATA.ViewPanelsType}, ... - 'Matrix',DATA.ViewMatrix); - end - viewimage_Callback('one') - %drawfunctions('drawall',1); - elseif ~isempty(DATA.LastView) && ismember(no,DATA.LastView.Panels) - lastview = DATA.LastView; - DATA.LastView = []; - panels = lastview.Panels; - DATA.CurrentPanel = find(panels==no,1); - drawfunctions('drawimageview',panels, ... - lastview.Matrix,lastview.PanelsType); - elseif SET(no).ZSize>1 - viewimage_Callback('montage'); - end; end -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); +if ~isnan(SET(no).RVEndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)) + if isempty(SET(no).EpiX) || isnan(SET(no).EpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)) + %RV exist and not LV Epi, then go for atrial scar + do = true; + end +end + +%--------------------------------------------- + function updatervstack +%--------------------------------------------- +%Updated the definition of RV stack number -%---------------------------- -function makeviewim(panel,no) -%---------------------------- -%Rearrange data to show all slices -global DATA SET NO +global DATA NO -myworkon; +if isempty(DATA.RVNO) + DATA.RVNO = NO; + if isfield(DATA.Handles,'rvstackpushbutton') + set(DATA.Handles.rvstackpushbutton,'String', sprintf('Stack #%d',DATA.RVNO)) + end +end +segment('updatevolume'); +% DATA.updateaxestables('volume') -if nargin==0 - panel = DATA.CurrentPanel; -end; +%--------------------------------------------- + function updatelvstack +%--------------------------------------------- +%Updated the definition of LV stack number -if nargin<2 - %This clause is needed when called from GUI. - no = NO; -end; +global DATA NO -if isempty(SET(no).CurrentSlice) - SET(no).CurrentSlice=1; - SET(no).StartSlice=1; - SET(no).EndSlice=1; +if isempty(DATA.LVNO) && isfield(DATA.Handles,'lvstackpushbutton') + DATA.LVNO = NO; + set(DATA.Handles.lvstackpushbutton,'String', sprintf('Stack #%d',DATA.LVNO)) end +segment('updatevolume'); +% DATA.updateaxestables('volume') -im=SET(no).IM; +%-------------------------------------------------- +function [xout,yout] = interphelper(pinx,piny) +%-------------------------------------------------- +%Interpolates points to create a contour without loops. +global DATA -% if strcmp(DATA.CurrentTool,'orthoview') && (SET(NO).ZSize==1) -% mywarning('Cannot display orthoview. One slice in the stack') -% DATA.ViewIM{panel}=[]; -% DATA.Currenttool='one' -% return -% end +%Since RV addition we need to manage nan entries here +pinx=pinx(~isnan(pinx)); +piny=piny(~isnan(piny)); + +xout = []; %#ok +yout = []; %#ok -%Add papillary visualization, connected to LV hide / show -%Weirdest problem ever apparently entering a zero indexes into a ct image -%is extremely timeconsuming. Therefore extra if case -stateandicon=segment('iconson','hidelv'); -%if not(stateandicon{1}) && any(SET(no).PapillaryIM==0) % not(isempty(SET(no).PapillaryIM)) && isequal(get(DATA.Handles.hidepapicon,'state'),'off') -if not(stateandicon{1}) && (~isempty(SET(no).PapillaryIM)) % not(isempty(SET(no).PapillaryIM)) && isequal(get(DATA.Handles.hidepapicon,'state'),'off') - im(SET(no).PapillaryIM)=DATA.GUISettings.PapilarColor; +if (length(pinx)<4) + xout = NaN*ones(DATA.NumPoints,1); + yout = xout; + return; end +%--- Generate output -% %Make sure viewpixelyicon is in the right state -% if DATA.Pref.ViewInterpolated -% % set(DATA.Handles.viewpixelyicon,'state','off'); -% set(DATA.Handles.viewpixelsmenu,'Checked','off'); -% else -% % set(DATA.Handles.viewpixelyicon,'state','on'); -% set(DATA.Handles.viewpixelsmenu,'Checked','on'); -% end +reppinx = [pinx;pinx;pinx]; +reppiny = [piny;piny;piny]; -scale = 2; +%Find distance between them +d = [0;cumsum(sqrt(diff(reppinx).^2+diff(reppiny).^2))]; +%Remve duplicate points +ind = [1;diff(d)]>1e-3; +reppinx = reppinx(ind); +reppiny = reppiny(ind); +d = d(ind); -switch DATA.ViewPanelsType{panel} - case {'one','mmodespatial','ortho'} - if DATA.Pref.ViewInterpolated && ~strcmp(DATA.ViewPanelsType{panel},'ortho') - imxsz = SET(no).XSize*scale; - imysz = SET(no).YSize*scale; - imip = cast(zeros(imxsz,imysz,SET(no).TSize),'like',SET(no).IM); - for t = 1:SET(no).TSize - imip(:,:,t) = imresize(im(:,:,t,SET(no).CurrentSlice),[imxsz imysz],'bilinear'); - end - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',imip,no); - %SET(no).NormalZoomState = [0.5;imysz+0.5;0.5;imxsz+0.5]; - %SET(no).ResolutionX = SET(no).ResolutionX*imxsz/SET(no).XSize; - %SET(no).ResolutionY = SET(no).ResolutionY*imxsz/SET(no).YSize; - else - %ugly hack to handle orthoview mode in the right cases - if strcmp(DATA.ViewPanelsType{panel},'ortho')&& ... - ~isempty(DATA.ViewIM) && ... - (size(DATA.ViewIM{1},4) ~= SET(no).ZSize || size(DATA.ViewIM{1},5) < size(SET(no).Colormap,2)) - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im,no); - elseif ~strcmp(DATA.ViewPanelsType{panel},'ortho') || panel ~= 1 - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im(:,:,:,SET(no).CurrentSlice),no); - elseif strcmp(DATA.ViewPanelsType{panel},'ortho')&&(SET(no).CurrentSlice==1) - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im(:,:,:,SET(no).CurrentSlice),no); - end - end - case 'orthomip' - if DATA.Pref.ViewInterpolated - imxsz = SET(no).XSize*scale; - imysz = SET(no).YSize*scale; - imip = cast(zeros(imxsz,imysz,SET(no).TSize),'like',SET(no).IM); - for t = 1:SET(no).TSize - imip(:,:,t) = imresize(max(im(:,:,t,:),[],4),[imxsz imysz],'bilinear'); - end - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',imip,no); - %SET(no).NormalZoomState = [0.5;imysz+0.5;0.5;imxsz+0.5]; - %SET(no).ResolutionX = SET(no).ResolutionX*imxsz/SET(no).XSize; - %SET(no).ResolutionY = SET(no).ResolutionY*imxsz/SET(no).YSize; - else - %ugly hack to handle orthoview mode in the right cases - if strcmp(DATA.ViewPanelsType{panel},'ortho')&& ... - ~isempty(DATA.ViewIM) && ... - (size(DATA.ViewIM{1},4) ~= SET(no).ZSize || size(DATA.ViewIM{1},5) < size(SET(no).Colormap,2)) - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im,no); - elseif strcmp(DATA.ViewPanelsType{panel},'orthomip')&& ... - ~isempty(DATA.ViewIM) && ... - (size(DATA.ViewIM{1},4) ~= SET(no).ZSize || size(DATA.ViewIM{1},5) < size(SET(no).Colormap,2)) - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',max(im,[],4),no); - elseif ~strncmp(DATA.ViewPanelsType{panel},'ortho',5) || panel ~= 1 - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im(:,:,:,SET(no).CurrentSlice),no); - end - end - case 'sag3DP' - DATA.ViewIM{panel} = segment3dp.tools('getoverlayimage','g'); - case 'trans3DP' - DATA.ViewIM{panel} =segment3dp.tools('getoverlayimage','r'); - case 'cor3DP' - DATA.ViewIM{panel} = segment3dp.tools('getoverlayimage','b'); - case 'speedim' - %Get the image - tempimage = segment3dp.tools('getimage',SET(NO).LevelSet.Pen.Color); - - %Remap the image - intensitymap = SET(NO).LevelSet.Speed.IntensityMap; - - tempremapped = fastremap(tempimage,intensitymap,int16(SET(NO).minValue),int16(SET(NO).maxValue)); %Doesnt work with color - tempremapped = single(tempremapped)/4000+0.5; %scale it 0...1 - tempremapped = uint8(tempremapped*255)+1; %scale it to 1..256 - %tempremapped = round((tempremapped(:)/4000+0.5)*255)+1; - - %convert colormap to uint8 - cmap = DATA.LevelSet.colormap; - cmap = uint8(255*cmap); - temprgb = cat(2,... - cmap(tempremapped,1),... - cmap(tempremapped,2),... - cmap(tempremapped,3)); - DATA.ViewIM{panel} = reshape(temprgb,[size(tempimage,1) size(tempimage,2) 3]); - %im = segment3dp.tools('getimagehelper',SET(no).LevelSet.SpeedIM,SET(no).LevelSet.Pen.Color); - %DATA.ViewIM{panel} = reshape(calcfunctions('remapuint8',single(im)/4000+0.5,no,DATA.LevelSet.colormap),... - %[size(im) 1 1 3]); - case 'hla' -% if strcmp(DATA.CurrentTool,'orthoview') && (SET(NO).TSize > 0) -% mywarning(dprintf('Orthoview is not available for time resolved images.')) -% return -% end - if strcmp(DATA.CurrentTool,'orthoview') - DATA.ViewIM{panel} = permute(DATA.ViewIM{1}(SET(no).HLA.slice,:,:,:,:),[4 2 3 1 5]); - else - im = permute(SET(no).IM(SET(no).HLA.slice,:,:,:),[4 2 3 1]); - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im,no); - end - case 'hlamip' - im = permute(max(SET(no).IM,[],1),[4 2 3 1]); - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im,no); - case 'vla' - % if strcmp(DATA.CurrentTool,'orthoview') && (SET(NO).TSize > 0) - % mywarning(dprintf('Orthoview is not available for time resolved images.')) - % return - % end - if strcmp(DATA.CurrentTool,'orthoview') - DATA.ViewIM{panel} = permute(DATA.ViewIM{1}(:,SET(no).VLA.slice,:,:,:),[4 1 3 2 5]); - else - im = permute(SET(no).IM(:,SET(no).VLA.slice,:,:),[4 1 3 2]); - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im,no); - end - case 'vlamip' - im = permute(max(SET(no).IM,[],2),[4 1 3 2]); - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im,no); - case 'gla' - glaangle = SET(no).GLA.angle; - - %Define coordinates of midpoint and find image edge - x0 = SET(no).HLA.slice; - y0 = SET(no).VLA.slice; - tlim = zeros(1,4); - %Here should SET(no).ResolutionX and ResolutionY be introduced somehow - tlim(1) = SET(no).ResolutionX*(1-SET(no).HLA.slice)/sin(glaangle); - tlim(2) = SET(no).ResolutionY*(1-SET(no).VLA.slice)/cos(glaangle); - %tmin = max(tx,ty); - tlim(3) = SET(no).ResolutionX*(SET(no).XSize-SET(no).HLA.slice)/sin(glaangle); - tlim(4) = SET(no).ResolutionY*(SET(no).YSize-SET(no).VLA.slice)/cos(glaangle); - %tmax = min(tx,ty); - tlim = sort(tlim); - tmin = tlim(2); - tmax = tlim(3); - - t0 = SET(no).CurrentTimeFrame; - z0 = SET(no).CurrentSlice; - - %Define extension - sz = round(SET(no).YSize*cos(glaangle)^2+SET(no).XSize*sin(glaangle)^2); - res = SET(NO).ResolutionY*cos(glaangle)+SET(NO).ResolutionX*abs(sin(glaangle)); - - if cos(glaangle) >= 0 - x = x0 + sin(glaangle)*(tmin:res:tmax)/SET(no).ResolutionX; %linspace(tmin,tmax,sz); - y = y0 + cos(glaangle)*(tmin:res:tmax)/SET(no).ResolutionY; %linspace(tmin,tmax,sz); - else - x = x0 + sin(glaangle)*(tmax:-res:tmin)/SET(no).ResolutionX; %linspace(tmin,tmax,sz); - y = y0 + cos(glaangle)*(tmax:-res:tmin)/SET(no).ResolutionY; - end - SET(no).GLA.x0 = x(1); - SET(no).GLA.y0 = y(1); - - t = 1:SET(no).TSize; - z = 1:SET(no).ZSize; - - %Define image axes in xy plane and along z and t axis - xyline = [x;y;t0*ones(size(x));z0*ones(size(x))]; - zline = [x0*ones(size(z));y0*ones(size(z));t0*ones(size(z));z]; - tline = [x0*ones(size(t));y0*ones(size(t));t;z0*ones(size(t))]; - - X = meshgrid(xyline(1,:),zline(1,:),tline(1,:)); - Y = meshgrid(xyline(2,:),zline(2,:),tline(2,:)); - [~,~,T] = meshgrid(xyline(3,:),zline(3,:),tline(3,:)); - [~,Z] = meshgrid(xyline(4,:),zline(4,:),tline(4,:)); - if strcmp(DATA.CurrentTool,'orthoview') - if size(DATA.ViewIM{1},3) == 1 - v = interpn(squeeze(DATA.ViewIM{1}),X,Y,Z,'nearest'); - - elseif size(DATA.ViewIM{1},4) == 1 - v = interpn(squeeze(SET(no).IM),X,Y,Z,'nearest'); - else - v = interpn(DATA.ViewIM{1},X,Y,T,Z,'nearest'); - end - else - if SET(no).TSize == 1 - im = interpn(squeeze(SET(no).IM),X,Y,Z,'nearest'); - else - im = interpn(SET(no).IM,X,Y,T,Z,'nearest'); - end - v = calcfunctions('remapuint8viewim',im,no); - end - DATA.ViewIM{panel} = v; - case 'glamip' - glaangle = SET(no).GLA.angle; - - %Define coordinates of midpoint and find image edge - x0 = SET(no).HLA.slice; - y0 = SET(no).VLA.slice; - tlim = zeros(1,4); - tlim(1) = SET(no).ResolutionX*(1-SET(no).HLA.slice)/sin(glaangle); - tlim(2) = SET(no).ResolutionY*(1-SET(no).VLA.slice)/cos(glaangle); - tlim(3) = SET(no).ResolutionX*(SET(no).XSize-SET(no).HLA.slice)/sin(glaangle); - tlim(4) = SET(no).ResolutionY*(SET(no).YSize-SET(no).VLA.slice)/cos(glaangle); - tlim = sort(tlim); - tmin = tlim(2); - tmax = tlim(3); - - t0 = SET(no).CurrentTimeFrame; - z0 = SET(no).CurrentSlice; - - %Define extension - sz = round(SET(no).YSize*cos(glaangle)^2+SET(no).XSize*sin(glaangle)^2); - res = SET(NO).ResolutionY*cos(glaangle)+SET(NO).ResolutionX*abs(sin(glaangle)); - - if cos(glaangle) >= 0 - x = x0 + sin(glaangle)*(tmin:res:tmax)/SET(no).ResolutionX; %linspace(tmin,tmax,sz); - y = y0 + cos(glaangle)*(tmin:res:tmax)/SET(no).ResolutionY; %linspace(tmin,tmax,sz); - else - x = x0 + sin(glaangle)*(tmax:-res:tmin)/SET(no).ResolutionX; %linspace(tmin,tmax,sz); - y = y0 + cos(glaangle)*(tmax:-res:tmin)/SET(no).ResolutionY; - end - SET(no).GLA.x0 = x(1); - SET(no).GLA.y0 = y(1); - - t = 1:SET(no).TSize; - z = 1:SET(no).ZSize; - - %Define image axes in xy plane and along z and t axis - xyline = [x;y;t0*ones(size(x));z0*ones(size(x))]; - zline = [x0*ones(size(z));y0*ones(size(z));t0*ones(size(z));z]; - tline = [x0*ones(size(t));y0*ones(size(t));t;z0*ones(size(t))]; - - X = meshgrid(xyline(1,:),zline(1,:),tline(1,:)); - Y = meshgrid(xyline(2,:),zline(2,:),tline(2,:)); - [~,~,T] = meshgrid(xyline(3,:),zline(3,:),tline(3,:)); - [~,Z] = meshgrid(xyline(4,:),zline(4,:),tline(4,:)); - if strcmp(DATA.CurrentTool,'orthoview') - if size(DATA.ViewIM{1},3) == 1 - v = interpn(squeeze(DATA.ViewIM{1}),X,Y,Z,'nearest'); - else - v = interpn(DATA.ViewIM{1},X,Y,T,Z,'nearest'); - end - else - if SET(no).TSize == 1 - im = interpn(squeeze(SET(no).IM),X,Y,Z,'nearest'); - else - im = interpn(SET(no).IM,X,Y,T,Z,'nearest'); - end - v = calcfunctions('remapuint8viewim',im,no); - end - DATA.ViewIM{panel} = v; - case {'realhla','realvla'} - type = upper(DATA.ViewPanelsType{panel}); - im = SET(no).(type).IM; - if DATA.Pref.ViewInterpolated - imxsz = size(im,1)*scale; - imysz = size(im,2)*scale; - im = zeros(imxsz,imysz,SET(no).TSize); - for t = 1:SET(no).TSize - im(:,:,t) = imresize(SET(no).(type).IM(:,:,t),[imxsz imysz],'bilinear'); - end - %SET(no).NormalZoomState = [0.5;imysz+0.5;0.5;imxsz+0.5]; - %SET(no).ResolutionX = SET(no).ResolutionX*imxsz/SET(no).XSize; - %SET(no).ResolutionY = SET(no).ResolutionY*imxsz/SET(no).YSize; - end - DATA.ViewIM{panel} = calcfunctions('remapuint8viewim',im(:,:,:),no); - case 'mmodetemporal' - DATA.ViewIM{panel} = []; - case {'montage','montagerow'} - %Update number of rows and columns - if isequal(DATA.ViewPanelsType{panel},'montage') - [rows,cols] = calcfunctions('calcrowscols',no); %.cols,.rows - DATA.ViewPanelsMatrix{panel} = [rows cols]; - else - if SET(no).ZSize>8 - DATA.ViewPanelsMatrix{panel}(1) = 2; - DATA.ViewPanelsMatrix{panel}(2) = ceil(SET(no).ZSize/2); - else - DATA.ViewPanelsMatrix{panel}(1) = 1; - DATA.ViewPanelsMatrix{panel}(2) = SET(no).ZSize; - end; - end; - DATA.ViewIM{panel} = calcfunctions('calcmontageviewim', ... - no,DATA.ViewPanelsMatrix{panel}); - case 'montagefit' - %Update number of rows and columns - if DATA.ViewMatrix(1) < DATA.ViewMatrix(2) - DATA.ViewPanelsMatrix{panel} = [SET(no).ZSize 1]; - else - DATA.ViewPanelsMatrix{panel} = [1 SET(no).ZSize]; - end; - - %Create space - if isempty(SET(no).Colormap) - DATA.ViewIM{panel} = repmat(uint8(0),[SET(no).XSize*DATA.ViewPanelsMatrix{panel}(1) SET(no).YSize*DATA.ViewPanelsMatrix{panel}(2) SET(no).TSize]); - else - DATA.ViewIM{panel} = repmat(uint8(0),[SET(no).XSize*DATA.ViewPanelsMatrix{panel}(1) SET(no).YSize*DATA.ViewPanelsMatrix{panel}(2) SET(no).TSize 3]); - end - - for tloop=1:SET(no).TSize - for zloop=1:SET(no).ZSize - c = 1+mod(zloop-1,DATA.ViewPanelsMatrix{panel}(2)); - r = ceil(zloop/DATA.ViewPanelsMatrix{panel}(2)); - DATA.ViewIM{panel}(... - (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... - (1+(c-1)*SET(no).YSize):(c*SET(no).YSize),tloop,:) = calcfunctions('remapuint8viewim',... - im(:,:,tloop,zloop),no); - end; - end; - case 'montagesegmented' - %Montage view of segmentedslices only - segslices = getmontagesegmentedslices(no); - [rows,cols] = calcfunctions('calcrowscols',no,numel(segslices)); %.cols,.rows - DATA.ViewPanelsMatrix{panel} = [rows cols]; - segmentedonly = true; - DATA.ViewIM{panel} = calcfunctions('calcmontageviewim', ... - no,DATA.ViewPanelsMatrix{panel},segmentedonly); - case 'sax3' - %Update number of rows and columns - if DATA.ViewMatrix(1) < DATA.ViewMatrix(2) - DATA.ViewPanelsMatrix{panel} = [3 1]; - else - DATA.ViewPanelsMatrix{panel} = [1 3]; - end; - - %Create space - if isempty(SET(no).Colormap) - DATA.ViewIM{panel} = repmat(uint8(0),[SET(no).XSize*DATA.ViewPanelsMatrix{panel}(1) SET(no).YSize*DATA.ViewPanelsMatrix{panel}(2) SET(no).TSize]); - else - DATA.ViewIM{panel} = repmat(uint8(0),[SET(no).XSize*DATA.ViewPanelsMatrix{panel}(1) SET(no).YSize*DATA.ViewPanelsMatrix{panel}(2) SET(no).TSize 3]); - end - - for tloop=1:SET(no).TSize - for zloop=1:3 - c = 1+mod(zloop-1,DATA.ViewPanelsMatrix{panel}(2)); - r = ceil(zloop/DATA.ViewPanelsMatrix{panel}(2)); - z = SET(no).SAX3.slices(zloop,tloop); - DATA.ViewIM{panel}(... - (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... - (1+(c-1)*SET(no).YSize):(c*SET(no).YSize),tloop,:) = calcfunctions('remapuint8viewim',... - im(:,:,tloop,z),no); - end; - end; -end; - -if isempty(DATA.Overlay) - DATA.Overlay = struct('alphadata',[],'cdata',[]); -end -DATA.Overlay(panel) = struct('alphadata',[],'cdata',[]); -myworkoff; - -%---------------------- -function montage_Motion %#ok -%---------------------- -%Motion function when selection slices in montage view. - -global DATA SET NO - -if DATA.Interactionlock - return; -end; - -[~,~,slice]=getclickedcoords; -% p = get(gca,'CurrentPoint'); -% x=p(1); -% y=p(1,2); -% -% col = 1+floor(x/SET(NO).YSize); -% row = 1+floor(y/SET(NO).XSize); -% slice = col+(row-1)*DATA.ViewPanelsMatrix{panel}(2); -if slice>=SET(NO).ZSize - slice = SET(NO).ZSize; -end; -if slice<1 - slice=1; -end; -temp = SET(NO).StartSlice; -SET(NO).StartSlice = min(SET(NO).ZSize,max(SET(NO).StartSlice,1)); -SET(NO).EndSlice = min(SET(NO).ZSize,max(SET(NO).EndSlice,1)); -SET(NO).StartSlice = min([SET(NO).StartSlice slice SET(NO).EndSlice]); -SET(NO).EndSlice = max([temp slice SET(NO).EndSlice]); - -%Update flows as well -if length(SET(NO).Linked) > 1 - nos = SET(NO).Linked; - for no=unique(nos) - %copy to linked flows - SET(no).StartSlice=SET(NO).StartSlice; - SET(no).CurrentSlice=SET(NO).CurrentSlice; - SET(no).EndSlice=SET(NO).EndSlice; - end -end -updateselectedslices; - -drawfunctions('drawsliceno'); - -%-------------------------------- -function montage_Buttonup(panel) %#ok -%-------------------------------- -%Button up fucntion for selecting slices in montage view. -global DATA NO - -if DATA.Interactionlock - return; -end; - -% updateoneim(NO); - -set(DATA.imagefig,'WindowButtonMotionFcn',''); -set(DATA.imagefig,'WindowButtonUpFcn',''); - -drawfunctions('drawsliceno',NO); - -%-------------------------------- -function montage_Buttondown(panel) %#ok -%-------------------------------- -%Button down function for selecting slices in montage view. -global DATA SET NO - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -%Extract coordinates clicked -[~,~,slice] = getclickedcoords; - -if (slice>SET(NO).ZSize)||(slice<1) - return; -end; - -%Check what type of click -switch get(DATA.imagefig,'SelectionType') - case 'extend' - %Shift-click to select range. - %Same selection code as montage_Motion - temp = SET(NO).StartSlice; - SET(NO).StartSlice = min(SET(NO).ZSize,max(SET(NO).StartSlice,1)); - SET(NO).EndSlice = min(SET(NO).ZSize,max(SET(NO).EndSlice,1)); - SET(NO).StartSlice = min([SET(NO).StartSlice slice SET(NO).EndSlice]); - SET(NO).EndSlice = max([temp slice SET(NO).EndSlice]); - - %Update flows as well - if length(SET(NO).Linked) > 1 - nos = SET(NO).Linked; - for no=unique(nos) - %copy to linked flows - SET(no).StartSlice=SET(NO).StartSlice; - SET(no).CurrentSlice=SET(NO).CurrentSlice; - SET(no).EndSlice=SET(NO).EndSlice; - end - end - - updateselectedslices; - drawfunctions('drawsliceno',NO); -% pan_Buttondown; %shift-click formerly panned. No longer, though still -% for one-view. - case 'normal' - set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''montage_Buttonup'')',mfilename)); - set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''montage_Motion'');',mfilename)); - switchtoslice(slice); - case 'alt' - if ~ismember(slice,SET(NO).StartSlice:SET(NO).EndSlice) - switchtoslice(slice); - end - DATA.contextmenu; - case 'open' - no = DATA.ViewPanels(DATA.CurrentPanel); - if numel(DATA.ViewPanels) > 1 - drawfunctions('drawall',1); - elseif SET(no).ZSize>1 - viewimage_Callback('one'); - end; -end; - -%---------------------- -function pan_Buttondown -%---------------------- -%Button down function for panning of current image panel -global DATA - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''pan_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''pan_Buttonup'')',mfilename)); - -%------------------------ -function pan_Motion(init) %#ok -%------------------------ -%Motion function of pan -global DATA -persistent startpos - -%If called with argument reset and exit. -if nargin>0 - startpos = []; - return; -end; - -panel = DATA.CurrentPanel; -ax = DATA.Handles.imageaxes(panel); - -%Get clicked point -[x,y] = mygetcurrentpoint(ax); - -if isempty(startpos) - startpos = [x y]; -end; - - -xlim = get(ax,'xlim'); -ylim = get(ax,'ylim'); -if ismember(DATA.ViewPanelsType{panel},{'montagefit','sax3'}) - if all(diff(DATA.ViewPanelsMatrix{panel}) > 0) - set(ax,... - 'xlim',xlim+startpos(1)-x); - else - set(ax,... - 'ylim',ylim+startpos(2)-y); - end -else - set(ax,... - 'xlim',xlim+startpos(1)-x,... - 'ylim',ylim+startpos(2)-y); -end - -drawfunctions('viewupdatetextposition'); -drawfunctions('viewupdateannotext'); - -%-------------------- -function pan_Buttonup %#ok -%-------------------- -%Button up function for panning. -global DATA SET NO - -%Reset startpos -pan_Motion(true); - -%Restore so no motion is called -set(DATA.imagefig,'WindowButtonMotionFcn',''); - -%Restore main buttonup function -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - -%Set zoom state for all linked image stacks -nos = SET(NO).Linked; -switch DATA.ViewPanelsType{DATA.CurrentPanel} - case {'one','ortho'} - [SET(nos).NormalZoomState] = deal([... - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'xlim')'; - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'ylim')']); - case 'montage' - [SET(nos).MontageZoomState] = deal([... - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'xlim')'; - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'ylim')']); - case 'montagerow' - [SET(nos).MontageRowZoomState] = deal([... - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'xlim')'; - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'ylim')']); - case {'montagefit','sax3','montagesegmented'} - [SET(nos).MontageFitZoomState] = deal([... - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'xlim')'; - get(DATA.Handles.imageaxes(DATA.CurrentPanel),'ylim')']); -end; - -drawfunctions('viewupdatetextposition'); -drawfunctions('viewupdateannotext'); - -%-------------------------- -function center_Motion %#ok -%-------------------------- -%Motion function of the center point. - -global DATA SET NO - -[x,y,slice] = getclickedcoords; -panel = DATA.CurrentPanel; -% first line is for montage -% second line is for one-view. -if (slice==SET(NO).CurrentSlice) && ... - (x>0.5) && (y>0.5) && (x -%-------------------------------- -%Called when center '+' is pressed down, sets motion and buttonup fcns. -global DATA SET NO - -switchtopanel(panel); - -if DATA.Interactionlock - return; -end; - -[~,~,slice] = getclickedcoords; -% If slice has changed, make sure montage/one are in sync -if (slice>SET(NO).ZSize) - return; -end -switchtoslice(slice); - -set(DATA.imagefig,'WindowButtonMotionFcn',sprintf('%s(''center_Motion'');',mfilename)); -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''center_Buttonup'')',mfilename)); - -%----------------------- -function center_Buttonup %#ok -%----------------------- -%This function is called when buttonup occurs after draging center point - -global DATA SET NO - -%Restore so no motion is called -set(DATA.imagefig,'WindowButtonMotionFcn',''); - -%Restore main buttonup function -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - -if length(SET(NO).Linked) > 1 - if ~isempty(SET(NO).Parent) - nos = SET(NO).Linked; - for loop=1:length(nos) - SET(nos(loop)).CenterX = SET(NO).CenterX; - SET(nos(loop)).CenterY = SET(NO).CenterY; - end; - end; -end; -drawfunctions('drawimageno'); - -%------------------------------ -function endo_Buttondown(panel) %#ok -%------------------------------ -%Button down function for manual draw of endocardium. -global DATA - -switchtopanel(panel); - -switch get(DATA.imagefig,'SelectionType') - case 'normal' - if isequal(get(DATA.Handles.endopenicon,'state'),'on') - manualdraw_Buttondown('endo',panel,0); %modify old - else - manualdraw_Buttondown('endo',panel,1); %add new - end; - case 'alt' - disp('Later add popup menu here.'); -end; - -%----------------------------- -function epi_Buttondown(panel) %#ok -%----------------------------- -%Button down function for manual draw of endocardium. -global DATA - -switchtopanel(panel); - -switch get(DATA.imagefig,'SelectionType') - case 'normal' - if isequal(get(DATA.Handles.epipenicon,'state'),'on') - manualdraw_Buttondown('epi',panel,0); %modify old - else - manualdraw_Buttondown('epi',panel,1); %add new - end; - case 'alt' - disp('Later add popup menu here.'); -end; - -%----------------------------- -function do = doatrialscar(no) -%----------------------------- -%Helper function to check if user input is for atrial scar or lv scar -%(default) - -global SET - -do = false; - -if isempty(SET(no).RVEndoX) - return; -end; - -if ~isnan(SET(no).RVEndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)) - if isempty(SET(no).EpiX) || isnan(SET(no).EpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)) - %RV exist and not LV Epi, then go for atrial scar - do = true; - end; -end; - -%--------------------------------------------- - function updatervstack -%--------------------------------------------- -%Updated the definition of RV stack number - -global DATA NO - -if isempty(DATA.RVNO) - DATA.RVNO = NO; - set(DATA.Handles.rvstackpushbutton,'String', sprintf('Stack #%d',DATA.RVNO)) -end -DATA.updateaxestables('volume') - -%--------------------------------------------- - function updatelvstack -%--------------------------------------------- -%Updated the definition of LV stack number - -global DATA NO - -if isempty(DATA.LVNO) - DATA.LVNO = NO; - set(DATA.Handles.lvstackpushbutton,'String', sprintf('Stack #%d',DATA.LVNO)) -end -DATA.updateaxestables('volume') - -%----------------------------------------- -function manualdraw_Buttonup(type,new,obj) %#ok -%----------------------------------------- -%Button up function for manual drawing. -global DATA SET NO - -if nargin<1 - type = 'endo'; -end; - -if nargin<2 - new = true; -end; - -if nargin==3 - try - set(obj,'LineWidth',DATA.Pref.LineWidth); - catch %#ok - end; -end; - -oldpref=DATA.ThisFrameOnly; - -%--- Use variable no instead of NO. If flow data -%set then point to magnitude data set. - -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -if ~isempty(SET(no).Flow) && strcmp(type,'roi') - DATA.ThisFrameOnly = false; -end - -dolvnoupdate = 0; -dorvnoupdate = 0; - -%check if resampling is needed -numpointscheck=[size(SET(no).EndoX,1),size(SET(no).RVEndoX,1),size(SET(no).EpiX,1),size(SET(no).RVEpiX,1)]; -numpointscheck(isnan(numpointscheck))=[]; -numpointscheck(numpointscheck==0)=[]; - -if any(DATA.NumPoints~=numpointscheck) - %Do all curve interpolations. this is safety measure only done - %occasionally when something has happened. - for loop=1:length(SET) - segpref('numpointsedithelper', loop); - segment('updatemodeldisplay',loop); - end; -end - -tools('enableundo',no); - -slice=SET(no).CurrentSlice; - -%If straintagging initiated adjust LVupdated -if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') - SET(no).StrainTagging.LVupdated = 1; -end - -%Restore -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); -if not(isempty(DATA.Handles.phasecursor)) - set(DATA.Handles.phasecursor,'visible','off'); -end; -DATA.Handles.phasecursor = []; - -DATA.buttonup_Callback; -set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''buttonup_Callback'')','segment'));%Restore - -%Extract data -x = DATA.CursorX(1:DATA.CursorN); -y = DATA.CursorY(1:DATA.CursorN); - -%Restore -DATA.CursorN = 0; - -%Calculate total length -if length(x)>1 - len = sqrt(... - conv2(x,[1 -1],'valid').^2+... - conv2(y,[1 -1],'valid').^2); - len = [0;len(:)]; %Add zero first - len = cumsum(len); - tempind = find(conv2(len,[1;-1],'valid')~=0); %Remove doublets - len = [len(1);len(tempind+1)]; - x = [x(1) x(tempind+1)]; - y = [y(1) y(tempind+1)]; - totallength = len(end); -else - drawfunctions('drawsliceno'); - % If No Scar data, clear the struct. (Handles empty clicks) - if ~isempty(SET(NO).Scar) - if ~any(SET(NO).Scar.Manual(:)) && ~any(SET(NO).Scar.Auto(:)) - viability('viabilityclear_Callback'); - end - end - return; -end; - -%Check if counterclock wise or clockwise -mx = mean(x); -my = mean(y); - -if max(abs(x-mx))>2*SET(no).XSize - disp('Got strange x-coordinates before interp1.'); - return; -end; - -if max(abs(y-my))>2*SET(no).YSize - disp('Got strange y-coordinates before interp1.'); - return; -end; - -if sum(unwrap(conv2(angle(complex(x-mx,y-my)),[1 -1],'valid')))<0 - x = fliplr(x); - y = fliplr(y); - %disp('counterclockwise'); -else - %disp('clockwise'); -end; - -%Resample -xr = interp1(len,x,linspace(0,totallength,DATA.NumPoints),'linear'); -yr = interp1(len,y,linspace(0,totallength,DATA.NumPoints),'linear'); -xr = xr(:); -yr = yr(:); - -if max(abs(xr-mx))>2*SET(no).XSize - myfailed('Got strange x-coordinates after interp1.',DATA.GUI.Segment); - return; -end; - -if max(abs(yr-my))>2*SET(no).YSize - myfailed('Got strange y-coordinates after interp1.',DATA.GUI.Segment); - return; -end; - -%This variable used to be dependent on ThisFrameOnly. Check is now done -%later in this fcn ---Correction this is in effect now. /Klas -%if DATA.ThisFrameOnly - timeframes = SET(no).CurrentTimeFrame; -%else -% timeframes = 1:SET(no).TSize;%SET(no).CurrentTimeFrame; -%end - -%numtimeframes=length(timeframes); - -if new - %--- Add end, resample to equidistant points - x= [x(:);x(1)]; - y= [y(:);y(1)]; - len = sqrt(... - conv2(x(:),[1;-1],'valid').^2+... - conv2(y(:),[1;-1],'valid').^2); - len = cumsum(len); - len = [0;len(:)]; %Add zero first - tempind = find(abs(conv2(len,[1;-1],'valid'))>1e-3); - len = [len(1);len(tempind+1)]; %remove doublets - x = [x(1);x(tempind+1)]; - y = [y(1);y(tempind+1)]; - totallength = len(end); - xr = interp1(len,x,linspace(0,totallength,DATA.NumPoints),'linear'); - yr = interp1(len,y,linspace(0,totallength,DATA.NumPoints),'linear'); - xr = xr(:); - yr = yr(:); -end; - -switch type - case {'scar','mo'} - %Check if it is atrial scar drawing, or normal LV scar - - %If atria scar then call special functions and exit otherwise continue - if doatrialscar(no) - atrialscar('manualdraw_Buttonup',no,type,xr,yr); - return; - end; - - if isempty(SET(no).Scar) - viability('viabilityreset_Callback'); - SET(no).Scar.Mode = 'manual'; - end; - - tempmask = createmask([SET(no).XSize SET(no).YSize],xr,yr) & SET(no).Scar.MyocardMask(:,:,slice); - temp = SET(no).Scar.Manual(:,:,slice); - - if isequal(type,'scar') - temp(tempmask) = int8(1); %Mark manual scar as 1 - else - temp(tempmask) = int8(2); %Mark manually no reflow as 2 - end; - - SET(no).Scar.Manual(:,:,slice) = temp; - - if SET(no).Scar.UpdateDirectly - viability('viabilitycalc'); - end; - - drawfunctions('drawimageno'); - - return; - case 'rubberpen' - - %Check if atrial scar then call special code, otherwise continue - if doatrialscar(no) - atrialscar('manualdraw_Buttonup',no,type,xr,yr); - return; - end; - - if isempty(SET(no).Scar) - myfailed('You need to enter viability view mode before drawing infarct regions.',DATA.GUI.Segment); - return; - end; - - %Create mask - tempmask = createmask([SET(no).XSize SET(no).YSize],xr,yr)&SET(no).Scar.MyocardMask(:,:,slice); - - %Update scar - temp = SET(no).Scar.Manual(:,:,slice); - temp(tempmask) = int8(-1); - SET(no).Scar.Manual(:,:,slice) = temp; - - %Update noreflow - temp = SET(no).Scar.NoReflow(:,:,slice); - temp(tempmask) = 0; - SET(no).Scar.NoReflow(:,:,slice) = temp; - - if SET(no).Scar.UpdateDirectly - viability('viabilitycalc'); - end; - drawfunctions('drawimageno'); - - return; - case 'rubber' - if isempty(SET(no).Scar) - myfailed('You need to enter viability view mode before drawing infarct regions.',DATA.GUI.Segment); - return; - end; - tempmask = createmask([SET(no).XSize SET(no).YSize],xr,yr)&SET(no).Scar.MyocardMask(:,:,slice); - temp = SET(no).Scar.Manual(:,:,slice); - temp(tempmask) = int8(0); - SET(no).Scar.Manual(:,:,slice) = temp; - if SET(no).Scar.UpdateDirectly - viability('viabilitycalc'); - end; - - drawfunctions('drawimageno'); - %if not(specialgui) - % viability('viabilityshowedits_Callback','on'); - %end; - - return; - case 'drawmarpen' - mar('createmyocardmask'); - SET(no).MaR.Mode = 'manual'; - tempmask = createmask([SET(no).XSize SET(no).YSize],xr,yr)&SET(no).MaR.MyocardMask(:,:,timeframes,slice); - temp = SET(no).MaR.Manual(:,:,timeframes,slice); - - temp(tempmask) = int8(1); %Mark manual scar as 1 - SET(no).MaR.Manual(:,:,timeframes,slice) = temp; - mar('update'); - - drawfunctions('drawimageno'); - return; - case 'drawmarrubberpen' - mar('createmyocardmask'); - tempmask = createmask([SET(no).XSize SET(no).YSize],xr,yr)&SET(no).MaR.MyocardMask(:,:,timeframes,slice); - temp = SET(no).MaR.Manual(:,:,timeframes,slice); - temp(tempmask) = int8(-1); - SET(no).MaR.Manual(:,:,timeframes,slice) = temp; - mar('update'); - - drawfunctions('drawimageno'); - return; - case 'drawmarrubber' - mar('createmyocardmask'); - tempmask = createmask([SET(no).XSize SET(no).YSize],xr,yr)&SET(no).MaR.MyocardMask(:,:,timeframes,slice); - temp = SET(no).MaR.Manual(:,:,timeframes,slice); - temp(tempmask) = int8(0); - SET(no).MaR.Manual(:,:,timeframes,slice) = temp; - mar('update'); - - drawfunctions('drawimageno'); - return; -end; - -%--- Type is either roi, endo or epi => more advanced... -pindensity = 3; - -if new - %--- New - pindensity = 3; - - %Find startpoint - - [~,inda] = min(angle(complex(mx-xr,my-yr))); - - %Reshape - xr = xr'; - yr = yr'; - %Store it - switch type - case 'endo' - %New endo - if isempty(SET(no).EndoX) - SET(no).EndoX = nan([DATA.NumPoints SET(no).TSize SET(no).ZSize]); - SET(no).EndoY = SET(no).EndoX; - dolvnoupdate = 1; %update is done last so graphical stuff is done as fast as possible - end; - SET(no).EndoX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).EndoY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).EndoX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).EndoY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - case 'epi' - %New epi - if isempty(SET(no).EpiX) - SET(no).EpiX = nan([DATA.NumPoints SET(no).TSize SET(no).ZSize]); - SET(no).EpiY = SET(no).EpiX; - dolvnoupdate = 1; %update is done last so graphical stuff is done as fast as possible - end; - SET(no).EpiX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).EpiY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).EpiX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).EpiY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - case 'rvendo' - %New rv-endo - if isempty(SET(no).RVEndoX) - SET(no).RVEndoX = nan([DATA.NumPoints SET(no).TSize SET(no).ZSize]); - SET(no).RVEndoY = SET(no).RVEndoX; - dorvnoupdate = 1; %update is done last so graphical stuff is done as fast as possible - end; - SET(no).RVEndoX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).RVEndoY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).RVEndoX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).RVEndoY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - case 'rvepi' - %New rv-epi - if isempty(SET(no).RVEpiX) - SET(no).RVEpiX = nan([DATA.NumPoints SET(no).TSize SET(no).ZSize]); - SET(no).RVEpiY = SET(no).RVEpiX; - dorvnoupdate = 1; %update is done last so graphical stuff is done as fast as possible - end; - SET(no).RVEpiX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).RVEpiY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).RVEpiX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).RVEpiY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - case 'roi' - %New roi - roiok = DATA.manualdraw_Buttonup_roi(no,xr,yr,slice); - if ~roiok - return - end - otherwise - myfailed(dprintf('Unknown draw type:%s should not occur.',type),DATA.GUI.Segment); - return; - end; -end; - -if not(new) - %--- Not closed try to fit in - - %Extract - switch type - case 'endo' - contoury = SET(no).EndoX(:,timeframes,SET(no).CurrentSlice)'; - contourx = SET(no).EndoY(:,timeframes,SET(no).CurrentSlice)'; - case 'epi' - contoury = SET(no).EpiX(:,timeframes,SET(no).CurrentSlice)'; - contourx = SET(no).EpiY(:,timeframes,SET(no).CurrentSlice)'; - case 'rvendo' - contoury = SET(no).RVEndoX(:,timeframes,SET(no).CurrentSlice)'; - contourx = SET(no).RVEndoY(:,timeframes,SET(no).CurrentSlice)'; - case 'rvepi' - contoury = SET(no).RVEpiX(:,timeframes,SET(no).CurrentSlice)'; - contourx = SET(no).RVEpiY(:,timeframes,SET(no).CurrentSlice)'; - case 'roi' - no = roi('roifindmag'); - %--- Try to find correct roi - oldmin=1e9; - for rloop=1:SET(no).RoiN - if SET(no).CurrentSlice==SET(no).Roi(rloop).Z - temp = min(sqrt(... - (SET(no).Roi(rloop).X(:,SET(no).CurrentTimeFrame)-y(1)).^2+... - (SET(no).Roi(rloop).Y(:,SET(no).CurrentTimeFrame)-x(1)).^2)); - if tempendind - temp = startind; - startind = endind; - endind = temp; - end; - - %--- Find the two parts where the contour is cut. - %part1 - part1x = contourx(startind:endind); - part1y = contoury(startind:endind); - - %part2 - part2x = [contourx(endind:end) contourx(2:startind)]; - part2y = [contoury(endind:end) contoury(2:startind)]; - - %Test join to fit - if ... - ( (part1x(end)-x(1))^2 + (part1y(end)-y(1))^2 ) < ... - ( (part1x(end)-x(end))^2 + (part1y(end)-y(end))^2 ) - part1x = [part1x x]; - part1y = [part1y y]; - else - part1x = [part1x fliplr(x)]; - part1y = [part1y fliplr(y)]; - end; - area1 = stablepolyarea(part1x,part1y); - - if ... - ( (part2x(end)-x(1))^2 + (part2y(end)-y(1))^2 ) < ... - ( (part2x(end)-x(end))^2 + (part2y(end)-y(end))^2 ) - part2x = [part2x x]; - part2y = [part2y y]; - else - part2x = [part2x fliplr(x)]; - part2y = [part2y fliplr(y)]; - end; - area2 = stablepolyarea(part2x,part2y); - - %Take the largest area - if area1>area2 - newcontourx = part1x; - newcontoury = part1y; - else - newcontourx = part2x; - newcontoury = part2y; - end; - - %Resample to equidistant points - newlen = sqrt(... - conv2(newcontourx,[1 -1],'valid').^2+... - conv2(newcontoury,[1 -1],'valid').^2); - newlen = [0;newlen(:)]; %Add zero first - newlen = cumsum(newlen); - tempind = find(abs(conv2(newlen,[1;-1],'valid'))>1e-3); - newlen = [newlen(1);newlen(tempind+1)]; - newcontourx = [newcontourx(1) newcontourx(tempind+1)]; - newcontoury = [newcontoury(1) newcontoury(tempind+1)]; - newtotallength = newlen(end); - - xr = interp1(newlen,newcontourx,linspace(0,newtotallength,DATA.NumPoints),'linear'); - yr = interp1(newlen,newcontoury,linspace(0,newtotallength,DATA.NumPoints),'linear'); - - %Find startpoint - %[tempres,inda] = min(abs(angle(complex(mx-xr,my-yr)))); - [~,inda] = min(angle(complex(mx-xr,my-yr))); - - %Reshape - xr = xr'; - yr = yr'; - - %Store it - switch type - case 'endo' - SET(no).EndoX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).EndoY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).EndoX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).EndoY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - - %Remove interpolation points if existing - if ~isempty(SET(no).EndoInterpX) - [SET(no).EndoInterpX{timeframes,SET(no).CurrentSlice}] = deal([]); - [SET(no).EndoInterpY{timeframes,SET(no).CurrentSlice}] = deal([]); - end - case 'epi' - - SET(no).EpiX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).EpiY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).EpiX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).EpiY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - - %Remove interpolation points if existing - if ~isempty(SET(no).EpiInterpX) - [SET(no).EpiInterpX{timeframes,SET(no).CurrentSlice}] = deal([]); - [SET(no).EpiInterpY{timeframes,SET(no).CurrentSlice}] = deal([]); - end - case 'rvendo' - SET(no).RVEndoX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).RVEndoY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).RVEndoX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).RVEndoY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)';% SET(no).RVEndoX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = repmat(yr(inda:end),1,numtimeframes); - if ~isempty(SET(no).RVEndoInterpX) - [SET(no).RVEndoInterpX{timeframes,SET(no).CurrentSlice}] = deal([]); - [SET(no).RVEndoInterpY{timeframes,SET(no).CurrentSlice}] = deal([]); - end - case 'rvepi' - SET(no).RVEpiX(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = yr(inda:end)'; - SET(no).RVEpiY(1:(DATA.NumPoints-inda+1),timeframes,SET(no).CurrentSlice) = xr(inda:end)'; - SET(no).RVEpiX((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = yr(1:inda)'; - SET(no).RVEpiY((DATA.NumPoints+1-inda):end,timeframes,SET(no).CurrentSlice) = xr(1:inda)'; - %Remove interpolation points if existing - if ~isempty(SET(no).RVEpiInterpX) - [SET(no).RVEpiInterpX{timeframes,SET(no).CurrentSlice}] = deal([]); - [SET(no).RVEpiInterpY{timeframes,SET(no).CurrentSlice}] = deal([]); - end - case 'roi' - SET(no).Roi(SET(no).RoiCurrent).X(1:(DATA.NumPoints-inda+1),timeframes) = yr(inda:end)'; - SET(no).Roi(SET(no).RoiCurrent).Y(1:(DATA.NumPoints-inda+1),timeframes) = xr(inda:end)'; - SET(no).Roi(SET(no).RoiCurrent).X((DATA.NumPoints+1-inda):end,timeframes) = yr(1:inda)'; - SET(no).Roi(SET(no).RoiCurrent).Y((DATA.NumPoints+1-inda):end,timeframes) = xr(1:inda)'; - roi('roiforceapply'); - - %Calculate area and intensity of ROI - thisframeonly = true; - [~,SET(no).Roi(SET(no).RoiCurrent).Area(SET(no).CurrentTimeFrame)] = ... - calcfunctions('calcroiarea',no,SET(no).RoiCurrent,thisframeonly); - [m,sd]=calcfunctions('calcroiintensity',no,SET(no).RoiCurrent,false,thisframeonly); - SET(no).Roi(SET(no).RoiCurrent).Mean(SET(no).CurrentTimeFrame) = m; - SET(no).Roi(SET(no).RoiCurrent).StD(SET(no).CurrentTimeFrame) = sd; - end; -end; %Done not closed contour - -%--- Double check rotation direction -switch type - case 'endo' - xr = SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - yr = SET(no).EndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - case 'epi' - xr = SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - yr = SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - case 'rvendo' - xr = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - yr = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - case 'rvepi' - xr = SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - yr = SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - case 'roi' - xr = SET(no).Roi(SET(no).RoiCurrent).X(:,SET(no).CurrentTimeFrame); - yr = SET(no).Roi(SET(no).RoiCurrent).Y(:,SET(no).CurrentTimeFrame); -end; - -mx = mean(xr); -my = mean(yr); - -if sum(unwrap(conv2(angle(complex(xr-mx,yr-my)),[1;-1],'valid')))<0 - %disp('counterclockwise'); -else - %disp('Wrong direction detected. Fixed but please report to author'); - switch type - case 'endo' - for tloop=timeframes - SET(no).EndoX(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).EndoX(:,tloop,SET(no).CurrentSlice)); - SET(no).EndoY(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).EndoY(:,tloop,SET(no).CurrentSlice)); - end; - case 'epi' - for tloop=timeframes - SET(no).EpiX(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).EpiX(:,tloop,SET(no).CurrentSlice)); - SET(no).EpiY(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).EpiY(:,tloop,SET(no).CurrentSlice)); - end; - case 'rvendo' - for tloop=timeframes - SET(no).RVEndoX(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).RVEndoX(:,tloop,SET(no).CurrentSlice)); - SET(no).RVEndoY(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).RVEndoY(:,tloop,SET(no).CurrentSlice)); - end; - case 'rvepi' - for tloop=timeframes - SET(no).RVEpiX(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).RVEpiX(:,tloop,SET(no).CurrentSlice)); - SET(no).RVEpiY(:,tloop,SET(no).CurrentSlice) = flipud(SET(no).RVEpiY(:,tloop,SET(no).CurrentSlice)); - end; - case 'roi' - for tloop=timeframes - SET(no).Roi(SET(no).RoiCurrent).X(:,tloop) = flipud(SET(no).Roi(SET(no).RoiCurrent).X(:,tloop)); - SET(no).Roi(SET(no).RoiCurrent).Y(:,tloop) = flipud(SET(no).Roi(SET(no).RoiCurrent).Y(:,tloop)); - end; - roi('roiforceapply'); - end; -end; - -%Check if should copy to all timeframes -switch type - case 'endo' - if not(DATA.ThisFrameOnly) - %Copy segmentation to all timeframes - for tloop=1:SET(no).TSize - SET(no).EndoX(:,tloop,SET(no).CurrentSlice) = SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EndoY(:,tloop,SET(no).CurrentSlice) = SET(no).EndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'epi' - if not(DATA.ThisFrameOnly) - %Copy segmentation to all timeframes - for tloop=1:SET(no).TSize - SET(no).EpiX(:,tloop,SET(no).CurrentSlice) = SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EpiY(:,tloop,SET(no).CurrentSlice) = SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'rvendo' - if not(DATA.ThisFrameOnly) - %Copy segmentation to all timeframes - for tloop=1:SET(no).TSize - SET(no).RVEndoX(:,tloop,SET(no).CurrentSlice) = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEndoY(:,tloop,SET(no).CurrentSlice) = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'rvepi' - if not(DATA.ThisFrameOnly) - %Copy segmentation to all timeframes - for tloop=1:SET(no).TSize - SET(no).RVEpiX(:,tloop,SET(no).CurrentSlice) = SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEpiY(:,tloop,SET(no).CurrentSlice) = SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'roi' - if DATA.ThisFrameOnly && new - %Remove segmentation from all timeframes other than current - SET(no).Roi(SET(no).RoiCurrent).T = SET(no).CurrentTimeFrame; - roix = SET(no).Roi(SET(no).RoiCurrent).X(:,SET(no).CurrentTimeFrame); - roiy = SET(no).Roi(SET(no).RoiCurrent).Y(:,SET(no).CurrentTimeFrame); - SET(no).Roi(SET(no).RoiCurrent).X = nan(size(SET(no).Roi(SET(no).RoiCurrent).X)); - SET(no).Roi(SET(no).RoiCurrent).Y = nan(size(SET(no).Roi(SET(no).RoiCurrent).Y)); - SET(no).Roi(SET(no).RoiCurrent).X(:,SET(no).CurrentTimeFrame) = roix; - SET(no).Roi(SET(no).RoiCurrent).Y(:,SET(no).CurrentTimeFrame) = roiy; - end; -end; - -%--- Add pins -if (isequal(type,'endo')||isequal(type,'epi'))&&DATA.Pref.AddPoints - %Resample to equidistant points - x=x(:); - y=y(:); - len = sqrt(... - conv2(x,[1;-1],'valid').^2+... - conv2(y,[1;-1],'valid').^2); - len = [0;len(:)]; %Add zero first - len = cumsum(len); - tempind = find(conv2(len,[1;-1],'valid')~=0); - len = [len(1);len(tempind+1)]; %Remove doublets - x = [x(1);x(tempind+1)]; - y = [y(1);y(tempind+1)]; - totallength = len(end); - xi = interp1(len,x,linspace(0,totallength,round(totallength/pindensity)),'linear'); - yi = interp1(len,y,linspace(0,totallength,round(totallength/pindensity)),'linear'); - xi = xi(:); - yi = yi(:); - - %Put pins - switch type - case 'endo' - if isempty(SET(no).EndoPinX) - SET(no).EndoPinX = cell(SET(no).TSize,SET(no).ZSize); - SET(no).EndoPinY = cell(SET(no).TSize,SET(no).ZSize); - end; - SET(no).EndoPinX{SET(no).CurrentTimeFrame,slice} = ... - [SET(no).EndoPinX{SET(no).CurrentTimeFrame,slice};yi]; - SET(no).EndoPinY{SET(no).CurrentTimeFrame,slice} = ... - [SET(no).EndoPinY{SET(no).CurrentTimeFrame,slice};xi]; - case 'epi' - if isempty(SET(no).EpiPinX) - SET(no).EpiPinX = cell(SET(no).TSize,SET(no).ZSize); - SET(no).EpiPinY = cell(SET(no).TSize,SET(no).ZSize); - end; - SET(no).EpiPinX{SET(no).CurrentTimeFrame,slice} = ... - [SET(no).EpiPinX{SET(no).CurrentTimeFrame,slice};yi]; - SET(no).EpiPinY{SET(no).CurrentTimeFrame,slice} = ... - [SET(no).EpiPinY{SET(no).CurrentTimeFrame,slice};xi]; - end; -end; - -%Double check! -if isequal(type,'endo')||isequal(type,'epi') - checkconsistency(SET(no).CurrentTimeFrame,SET(no).CurrentSlice); -end; - -%Finalize & update -updatemodeldisplay; -lvsegchanged = true; updatevolume(lvsegchanged); -if isequal(type,'roi') - docalc = false; %Intensity and area already updated - %This is needed to initiate ROI handles. Slice update won't do - for panel = find(ismember(DATA.ViewPanels,[no SET(no).Children])) - if strcmp(DATA.ViewPanelsType{panel},'montage') - DATA.plotrois(panel,no,docalc); - else - DATA.drawroiinpanel(panel,docalc); - end - end - updatetool; %to set buttondown fcn for new contours -else - drawfunctions('drawallslices'); -end - -if ~isempty(SET(no).StrainTagging) - SET(no).StrainTagging.LVupdated=1; -end - -if oldpref~=DATA.ThisFrameOnly - DATA.ThisFrameOnly = oldpref; -end - -if dolvnoupdate - updatelvstack -end - -if dorvnoupdate - updatervstack -end - -%------------------------- -function manualdraw_Motion %#ok -%------------------------- -%Motion function for manual drawings. -global DATA SET NO - -[x,y,slice] = getclickedcoords; - -xofs = 0; -yofs = 0; -if any(strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},{'montage','montagerow','montagefit','sax3','montagesegmented'})) - if ~isequal(slice,SET(NO).CurrentSlice) - if abs(slice-SET(NO).CurrentSlice)==1 - xofs = slice-SET(NO).CurrentSlice; - else - yofs = sign(slice-SET(NO).CurrentSlice); - end; - end; -end; - -% first line is for montage -% second line is for one-view. -if (slice==SET(NO).CurrentSlice) && ... - (x>0.5) && (y>0.5) && (xSET(NO).ZSize) - return; - end - switchtoslice(slice); - - %Moved this before setting of buttonup and button - if any(strcmp({'scar','mo','rubberpen'},type)) - %if isempty(SET(NO).Scar) - hasLVseg = (not(isempty(SET(NO).EndoX)) && not(all(all(squeeze(isnan(SET(NO).EndoX(1,:,:))))))) && (not(isempty(SET(NO).EpiX)) && not(all(all(squeeze(isnan(SET(NO).EpiX(1,:,:))))))); - hasRVseg = not(isempty(SET(NO).RVEndoX)) && not(all(all(squeeze(isnan(SET(NO).RVEndoX(1,:,:)))))); - if SET(NO).TSize>1 || hasRVseg+hasLVseg < 1 - myfailed('Does not seem to be viability image stack.',DATA.GUI.Segment); - updatetool('select') - stateandicon_scar=iconson('scarpen'); - stateandicon_mo=iconson('mopen'); - stateandicon_drp=iconson('rubberscar'); - stateandicon_scar{2}.undent; - stateandicon_mo{2}.undent; - stateandicon_drp{2}.undent; - DATA.Handles.configiconholder.iconCell{1}.isindented=1; - DATA.Handles.configiconholder.iconCell{1}.cdataDisplay=DATA.Handles.configiconholder.iconCell{1}.cdataIndent; - DATA.Handles.configiconholder.render; - return; - end; - end - - %Set up buttonup. If 'obj' is set during the execution below, then - %WindowButtonUpFcn is remapped with obj passed on at the bottom of - %this function. Obj is used to bold and then unbold an item. - obj = []; - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''manualdraw_Buttonup'',''%s'',%d )',mfilename,type,new)); - - set(DATA.Handles.cursor(panel),'visible','on',... - 'xdata',NaN,'ydata',NaN); - - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''manualdraw_Motion'')',mfilename)) - - - DATA.CursorX = nan(1,256); - DATA.CursorY = nan(1,256); - DATA.CursorN = 0; - - [DATA.CursorYOfs,DATA.CursorXOfs] = calcfunctions('calcoffset',slice,[],NO,panel); - - distlimit = DATA.Pref.ContourAdjustDistance; - - set(DATA.Handles.cursor(panel),'linestyle','-'); - - switch type - case 'endo' - %Remove interpolation points if existing - if ~isempty(SET(NO).EndoInterpX) - [SET(NO).EndoInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}] = deal([]); - [SET(NO).EndoInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}] = deal([]); - end - set(DATA.Handles.cursor(panel),'color','r'); - if new - %Calc distance to contour - if isempty(SET(NO).EndoX) - dist = 2*distlimit; - else - dist = min(sqrt(... - (SET(NO).EndoX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice)-y).^2+... - (SET(NO).EndoY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice)-x).^2)); - end; - if dist1 -% myfailed('Does not seem to be viability image stack.',DATA.GUI.Segment); -% return; -% end; - - %Check if doing atrial scar or normal scar - if doatrialscar(NO) - %Need to do nothing. Initialization is taken care of in - %buttonup - else - viability('viabilityreset_Callback','manual'); - SET(NO).Scar.Mode='manual'; - viability('viabilitymenu'); - end; - end; - switch type - case 'scar' - set(DATA.Handles.cursor(panel),'color','y'); - case 'mo' - set(DATA.Handles.cursor(panel),'color','r'); - case 'rubberpen' - set(DATA.Handles.cursor(panel),'color','y','linestyle',':'); - case 'rubber' - set(DATA.Handles.cursor(panel),'color','w','linestyle','-'); - end; - case 'drawmarpen' - set(DATA.Handles.cursor(panel),'color','w','linestyle','-'); - case 'drawmarrubberpen' - set(DATA.Handles.cursor(panel),'color','w','linestyle',':'); - end; - - if ~isempty(obj) - set(obj,'LineWidth',2); - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''manualdraw_Buttonup'',''%s'',%d,%16.16f )',mfilename,type,new,obj)); - end - case 'extend' - pan_Buttondown; - case 'alt' - if strcmp(type,'roi') - roi('roiget','nomenu','coord'); - drawfunctions('drawallslices'); - end - DATA.contextmenu; -end; - -%-------------------------------------------------- -function [xout,yout] = interphelper(pinx,piny) -%-------------------------------------------------- -%Interpolates points to create a contour without loops. -global DATA - -%Since RV addition we need to manage nan entries here -pinx=pinx(~isnan(pinx)); -piny=piny(~isnan(piny)); - -xout = []; %#ok -yout = []; %#ok - -if (length(pinx)<4) - xout = NaN*ones(DATA.NumPoints,1); - yout = xout; - return; -end -%--- Generate output - -reppinx = [pinx;pinx;pinx]; -reppiny = [piny;piny;piny]; - -%Find distance between them -d = [0;cumsum(sqrt(diff(reppinx).^2+diff(reppiny).^2))]; - -%Remve duplicate points -ind = [1;diff(d)]>1e-3; -reppinx = reppinx(ind); -reppiny = reppiny(ind); -d = d(ind); - -%Interpolate, periodic boundaries -xout = interp1(d,reppinx,linspace(d(length(reppinx)/3+1),d(2*length(reppinx)/3+1),DATA.NumPoints),'pchip'); - -yout = interp1(d,reppiny,linspace(d(length(reppinx)/3+1),d(2*length(reppinx)/3+1),DATA.NumPoints),'pchip'); - -[xout,yout]=mypoly2cw(xout,yout); - -% if isopengui('strain.fig') -% straintagging.straintagging('updateinterp',1) -% straintagging.straintagging('updateimages') -% end - -%------------------------------------- -function tool=interptoolfromcoords(x,y,slice) -%------------------------------------- -%get tool from point -%valid for 'interpendo' 'interpepi' 'interprvendo' 'interprvepi' - -global SET NO; - -dist_min=ones(1,4)*1e6; -ret_tool={'interpendo' 'interpepi' 'interprvendo' 'interprvepi'}; - -if ~isempty(SET(NO).EndoInterpX), - [dist] = min(sqrt(... - (SET(NO).EndoInterpX{SET(NO).CurrentTimeFrame,slice}-y).^2+... - (SET(NO).EndoInterpY{SET(NO).CurrentTimeFrame,slice}-x).^2)); - if ~isempty(dist), - dist_min(1)=dist; - end -end - -if ~isempty(SET(NO).EpiInterpX) - [dist] = min(sqrt(... - (SET(NO).EpiInterpX{SET(NO).CurrentTimeFrame,slice}-y).^2+... - (SET(NO).EpiInterpY{SET(NO).CurrentTimeFrame,slice}-x).^2)); - if ~isempty(dist), - dist_min(2)=dist; - end -end - -if ~isempty(SET(NO).RVEndoInterpX), - [dist] = min(sqrt(... - (SET(NO).RVEndoInterpX{SET(NO).CurrentTimeFrame,slice}-y).^2+... - (SET(NO).RVEndoInterpY{SET(NO).CurrentTimeFrame,slice}-x).^2)); - if ~isempty(dist), - dist_min(3)=dist; - end -end - -if ~isempty(SET(NO).RVEpiInterpX), - [dist] = min(sqrt(... - (SET(NO).RVEpiInterpX{SET(NO).CurrentTimeFrame,slice}-y).^2+... - (SET(NO).RVEpiInterpY{SET(NO).CurrentTimeFrame,slice}-x).^2)); - if ~isempty(dist), - dist_min(4)=dist; - end -end - -[~,ind]=min(dist_min); -tool=ret_tool{ind}; - -%--------------------------------------------- -function interpdeletepointthisslicephase %#ok -%--------------------------------------------- -%Delete interp points this slice and phase. -global DATA SET NO - -tools('enableundo') -tool=DATA.CurrentTool; -if ~strcmp(tool,{'interpendo' 'interpepi' 'interprvendo' 'interprvepi'}), - [x,y,slice] = getclickedcoords; - tool=interptoolfromcoords(x,y,slice); -end - -switch tool - case 'interpendo' - SET(NO).EndoInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - SET(NO).EndoInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - case 'interpepi' - SET(NO).EpiInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - SET(NO).EpiInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - case 'interprvendo' - SET(NO).RVEndoInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - SET(NO).RVEndoInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - case 'interprvepi' - SET(NO).RVEpiInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; - SET(NO).RVEpiInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=[]; -end - -%If straintagging initiated adjust LVupdated -if ~isempty(SET(NO).StrainTagging) && isfield(SET(NO).StrainTagging, 'LVupdated') - SET(NO).StrainTagging.LVupdated = 1; -end - -updatemodeldisplay; -drawfunctions('drawsliceno'); - -%--------------------------------------------- -function interpdeletepointthisslice %#ok -%--------------------------------------------- -%Delete interp points this slice. -global DATA SET NO - -tools('enableundo') -tool=DATA.CurrentTool; -if ~strcmp(tool,{'interpendo' 'interpepi' 'interprvendo' 'interprvepi'}), - [x,y,slice] = getclickedcoords; - tool=interptoolfromcoords(x,y,slice); -end - -for tloop=1:SET(NO).TSize - switch tool - case 'interpendo' - SET(NO).EndoInterpX{tloop,SET(NO).CurrentSlice}=[]; - SET(NO).EndoInterpY{tloop,SET(NO).CurrentSlice}=[]; - case 'interpepi' - SET(NO).EpiInterpX{tloop,SET(NO).CurrentSlice}=[]; - SET(NO).EpiInterpY{tloop,SET(NO).CurrentSlice}=[]; - case 'interprvendo' - SET(NO).RVEndoInterpX{tloop,SET(NO).CurrentSlice}=[]; - SET(NO).RVEndoInterpY{tloop,SET(NO).CurrentSlice}=[]; - case 'interprvepi' - SET(NO).RVEpiInterpX{tloop,SET(NO).CurrentSlice}=[]; - SET(NO).RVEpiInterpY{tloop,SET(NO).CurrentSlice}=[]; - end -end - -%If straintagging initiated adjust LVupdated -if ~isempty(SET(NO).StrainTagging) && isfield(SET(NO).StrainTagging, 'LVupdated') - SET(NO).StrainTagging.LVupdated = 1; -end - -updatemodeldisplay; -drawfunctions('drawsliceno'); - -%--------------------------------------------- -function interpdeletepointall %#ok -%--------------------------------------------- -%Delete interp points for all slices timeframes -global DATA SET NO - -tools('enableundo') -tool=DATA.CurrentTool; -if ~strcmp(tool,{'interpendo' 'interpepi' 'interprvendo' 'interprvepi'}), - [x,y,slice] = getclickedcoords; - tool=interptoolfromcoords(x,y,slice); -end - -for tloop=1:SET(NO).TSize - for zloop=1:SET(NO).ZSize - switch tool - case 'interpendo' - SET(NO).EndoInterpX{tloop,zloop}=[]; - SET(NO).EndoInterpY{tloop,zloop}=[]; - case 'interpepi' - SET(NO).EpiInterpX{tloop,zloop}=[]; - SET(NO).EpiInterpY{tloop,zloop}=[]; - case 'interprvendo' - SET(NO).RVEndoInterpX{tloop,zloop}=[]; - SET(NO).RVEndoInterpY{tloop,zloop}=[]; - case 'interprvepi' - SET(NO).RVEpiInterpX{tloop,zloop}=[]; - SET(NO).RVEpiInterpY{tloop,zloop}=[]; - end - end -end - -%If straintagging initiated adjust LVupdated -if ~isempty(SET(NO).StrainTagging) && isfield(SET(NO).StrainTagging, 'LVupdated') - SET(NO).StrainTagging.LVupdated = 1; -end - -updatemodeldisplay; -drawfunctions('drawsliceno'); - -%--------------------------------------------- -function interpdeletepoint %#ok -%--------------------------------------------- -%Delete interp point. -global DATA SET NO - -[x,y,slice] = getclickedcoords; -distlimit = DATA.Pref.ContourAdjustDistance; - -tool=DATA.CurrentTool; -if ~strcmp(tool,{'interpendo' 'interpepi' 'interprvendo' 'interprvepi'}), - tool=interptoolfromcoords(x,y,slice); -end - -switch tool - case 'interpendo' - [dist,delind] = min(sqrt(... - (SET(NO).EndoInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}-y).^2+... - (SET(NO).EndoInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}-x).^2)); - if ~(dist -%-------------------------------------------------- -%Guess points in current selection then moves to corrosponding tool. -global SET NO DATA - -if (nargin<2)||isempty(panel) - panel=DATA.CurrentPanel; -else - switchtopanel(panel); -end - -if (nargin<1)||isempty(type) - %Annoying but easy way to get type from context menu calls. - % Means that you can't change another type of contour from one tool. - switch DATA.CurrentTool - case 'interpendo' - type='endo'; - case 'interpepi' - type='epi'; - case 'interprvendo' - type='rvendo'; - case 'interprvepi' - type='rvepi'; - otherwise - disp('Count not find tool. Should not happen if handles are properly assigned/reassigned.'); - return; - end -end; - -[~,~,slice] = getclickedcoords; %only care about slice -if (slice>SET(NO).ZSize) - return; -end -switchtoslice(slice); - -switch type, - case 'endo' - if isempty(SET(NO).EndoX) - mywarning('Could not find contour to base guess on. Aborting!',DATA.GUI.Segment); - return; - else - if any(isnan(SET(NO).EndoX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice))) - mywarning('Could not find contour to base guess on. Aborting!',DATA.GUI.Segment); - return; - end - end - if ~isempty(SET(NO).EndoInterpX) - if ~isempty(SET(NO).EndoInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}) - if ~yesno('There is pin content in current selection. Do you want to remove it?',[],DATA.GUI.Segment) - return; - end - end - end - - [x,y]=pointsfromcontour(... - SET(NO).EndoX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice),... - SET(NO).EndoY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice),16); - - SET(NO).EndoInterpX{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=x; - SET(NO).EndoInterpY{SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice}=y; - - if size(SET(NO).EndoInterpX,1)=add many points. - %Interpolate points - newcontourx = contourx(:,tf,slice); - newcontoury = contoury(:,tf,slice); - n = size(contourx,1); - nstep = n/DATA.Pref.NumInterpPoints; %Later take from preferences. - newcontourx = newcontourx(round(1:nstep:n)); - newcontoury = newcontoury(round(1:nstep:n)); - newcontourx = newcontourx(:); - newcontoury = newcontoury(:); - y = []; %Do not add the point - x = []; %Do not add the point - else - %Contour and previous points exist => find closest gap - pinx = [interpx{tf,slice}; y]; - piny = [interpy{tf,slice}; x]; - contx = contourx(:,tf,slice); - conty = contoury(:,tf,slice); - - pinxrep=repmat(pinx',[length(contx) 1]); - contxrep=repmat(contx,[1 length(pinx)]); - pinyrep=repmat(piny',[length(conty) 1]); - contyrep=repmat(conty,[1 length(piny)]); - pindist2cont = (pinxrep-contxrep).^2+(pinyrep-contyrep).^2; - [~,mindistindex] =min(pindist2cont); - [~,sortindex] =sort(mindistindex); - pinx=pinx(sortindex); - piny=piny(sortindex); - - interpx{tf,slice}=pinx; - interpy{tf,slice}=piny; - - y = []; %Do not add the point - x = []; %Do not add the point - end; -end; - -%Add points -interpx{tf,slice} = [... - interpx{tf,slice} ; ... - newcontourx;y]; -interpy{tf,slice} = [... - interpy{tf,slice} ; ... - newcontoury;x]; - -%Store what pin -pinx=interpx{tf,slice}; -piny=interpy{tf,slice}; -[~,index]=min((pinx-origy).^2+(piny-origx).^2); -DATA.Pin = index; - -%--------------------------------------------- -function interpdraw_Buttondown(panel,type,forcedraw) -%--------------------------------------------- -%Button down function to draw interp points. -global DATA SET NO -%profile on - -if DATA.Interactionlock - return; -end; - -if (nargin<1)||isempty(panel) - panel=DATA.CurrentPanel; %#ok - killbuttondown = 0; -else - killbuttondown = switchtopanel(panel); -end - -if killbuttondown - return -end - -if isequal(DATA.CurrentTool,'select') - return; -end - -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end - -% if strcmp(DATA.ProgramName,'Segment CMR') -% DATA.ThisFrameOnly = true; -% end - -if (nargin<2)||isempty(type) - %Annoying but easy way to get type from context menu calls. - % Means that you can't change another type of contour from one tool. - switch DATA.CurrentTool - case 'interpendo' - type='endo'; - case 'interpepi' - type='epi'; - case 'interprvendo' - type='rvendo'; - case 'interprvepi' - type='rvepi'; - otherwise - %shouldn't happen, if handles are properly assigned/reassigned. - return; - end -end; - -if nargin<3 - forcedraw=false; -end - -[x,y,slice] = getclickedcoords; -% If slice has changed, make sure montage/one are in sync -if (slice>SET(no).ZSize) - return; -end -switchtoslice(slice); - -%Check what type of click -if ~(forcedraw) - switcher=get(DATA.imagefig,'SelectionType'); - tools('enableundo') %only push undo stack when not forcedrawn -else - switcher = 'extend'; -end - -switch switcher - case 'normal' - - % Distance check. Check to see if we haven't clicked close to something - - nomotion=false; - - %Add new points depending if contour exists etc. - switch type - case 'endo' - [SET(no).EndoInterpX,SET(no).EndoInterpY] = interpdrawhelper(... - SET(no).EndoInterpX,... - SET(no).EndoInterpY,... - SET(no).EndoX,... - SET(no).EndoY,x,y); - case 'epi' - [SET(no).EpiInterpX,SET(no).EpiInterpY] = interpdrawhelper(... - SET(no).EpiInterpX,... - SET(no).EpiInterpY,... - SET(no).EpiX,... - SET(no).EpiY,x,y); - case 'rvendo' - [SET(no).RVEndoInterpX,SET(no).RVEndoInterpY] = interpdrawhelper(... - SET(no).RVEndoInterpX,... - SET(no).RVEndoInterpY,... - SET(no).RVEndoX,... - SET(no).RVEndoY,x,y); - case 'rvepi' - [SET(no).RVEpiInterpX,SET(no).RVEpiInterpY] = interpdrawhelper(... - SET(no).RVEpiInterpX,... - SET(no).RVEpiInterpY,... - SET(no).RVEpiX,... - SET(no).RVEpiY,x,y); - end; - - if ~(nomotion) - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''interppointMotion'',''%s'')',mfilename,type)); - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''interppointButtonup'',''%s'')',mfilename,type)); - end - case 'extend' %shift click - switch type - case 'endo' - contourexists=... - ~isempty(SET(no).EndoX)&&... - ~any(isnan(SET(no).EndoX(:,SET(no).CurrentTimeFrame,slice))); - interpcellexist = ~isempty(SET(no).EndoInterpX); - case 'epi' - contourexists=... - ~isempty(SET(no).EpiX)&&... - ~any(isnan(SET(no).EpiX(:,SET(no).CurrentTimeFrame,slice))); - interpcellexist = ~isempty(SET(no).EpiInterpX); - case 'rvendo' - contourexists=... - ~isempty(SET(no).RVEndoX)&&... - ~any(isnan(SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,slice))); - interpcellexist = ~isempty(SET(no).RVEndoInterpX); - case 'rvepi' - contourexists=... - ~isempty(SET(no).RVEpiX)&&... - ~any(isnan(SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,slice))); - interpcellexist = ~isempty(SET(no).RVEpiInterpX); - end - - if ~interpcellexist && ~contourexists - return; - end - - switch type - case 'endo' - if isempty(SET(no).EndoX) - SET(no).EndoX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - SET(no).EndoY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - end; - [xout,yout] = interphelper(... - SET(no).EndoInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).EndoInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).EndoX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).EndoY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - case 'epi' - if isempty(SET(no).EpiX) - SET(no).EpiX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - SET(no).EpiY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - end; - [xout,yout] = interphelper(... - SET(no).EpiInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).EpiInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).EpiX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).EpiY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - case 'rvendo' - if isempty(SET(no).RVEndoX) - SET(no).RVEndoX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - SET(no).RVEndoY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - end; - [xout,yout] = interphelper(... - SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - case 'rvepi' - if isempty(SET(no).RVEpiX) - SET(no).RVEpiX = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - SET(no).RVEpiY = nan(DATA.NumPoints,SET(no).TSize,SET(no).ZSize); - end; - [xout,yout] = interphelper(... - SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - otherwise - %nothing - end; - %Check if should copy to all timeframes. Contour is copied if: - % - SingleFrameOnly is actived - % - There are no interpolation points in any other other timeframes. - switch type - case 'endo' - isemptymatrix=cellfun(@isempty,SET(no).EndoInterpX); - if not(DATA.ThisFrameOnly)&&... - (sum(~isemptymatrix(:,SET(no).CurrentSlice))<2) - %Copy segmentation to all slices - for tloop=1:SET(no).TSize - SET(no).EndoX(:,tloop,SET(no).CurrentSlice) = SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EndoY(:,tloop,SET(no).CurrentSlice) = SET(no).EndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'epi' - isemptymatrix=cellfun(@isempty,SET(no).EpiInterpX); - if not(DATA.ThisFrameOnly)&&... - (sum(~isemptymatrix(:,SET(no).CurrentSlice))<2) - %Copy segmentation to all slices - for tloop=1:SET(no).TSize - SET(no).EpiX(:,tloop,SET(no).CurrentSlice) = SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EpiY(:,tloop,SET(no).CurrentSlice) = SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'rvendo' - isemptymatrix=cellfun(@isempty,SET(no).RVEndoInterpX); - if not(DATA.ThisFrameOnly)&&... - (sum(~isemptymatrix(:,SET(no).CurrentSlice))<2) - %Copy segmentation to all slices - for tloop=1:SET(no).TSize - SET(no).RVEndoX(:,tloop,SET(no).CurrentSlice) = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEndoY(:,tloop,SET(no).CurrentSlice) = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - case 'rvepi' - isemptymatrix=cellfun(@isempty,SET(no).RVEpiInterpX); - if not(DATA.ThisFrameOnly)&&... - (sum(~isemptymatrix(:,SET(no).CurrentSlice))<2) - %Copy segmentation to all slices - for tloop=1:SET(no).TSize - SET(no).RVEpiX(:,tloop,SET(no).CurrentSlice) = SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEpiY(:,tloop,SET(no).CurrentSlice) = SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; - end; - lvsegchanged = true; - updatevolume(lvsegchanged); - case 'alt' - DATA.contextmenu; -end; - -%Test -if ~isempty(SET(no).StrainTagging) - SET(no).StrainTagging.LVupdated=1; -end - -checkconsistency; -updateselectedslices; -updatemodeldisplay; -drawfunctions('drawsliceno'); - -%-------------------- -function interppointButtonup(type) %#ok -%-------------------- -%Button up function for interp points. -global DATA SET NO - -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -dolvnoupdate = 0; -dorvnoupdate = 0; - -switch type - case 'endo' - contourexists=... - ~isempty(SET(no).EndoX)&&... - ~any(isnan(SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))); - dolvnoupdate=1; - case 'epi' - contourexists=... - ~isempty(SET(no).EpiX)&&... - ~any(isnan(SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))); - dolvnoupdate=1; - case 'rvendo' - contourexists=... - ~isempty(SET(no).RVEndoX)&&... - ~any(isnan(SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))); - dorvnoupdate=1; - case 'rvepi' - contourexists=... - ~isempty(SET(no).RVEpiX)&&... - ~any(isnan(SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))); - dorvnoupdate=1; -end - -checkconsistency; -set(DATA.imagefig,'WindowButtonMotionFcn',''); -if contourexists - interpdraw_Buttondown([],[],true); -end -%set(DATA.fig,'WindowButtonMotionFcn',@DATA.toggleplaceholdermotion) -updatemodeldisplay; -updatevolume; -drawfunctions('drawallslices'); - -if dolvnoupdate - updatelvstack -end - -if dorvnoupdate - updatervstack -end -%profile report - -%--------------------------------------------- -function interppointMotion(type) %#ok -%--------------------------------------------- -%Motion function for interp points. -global DATA SET NO - -no = NO; -if ~isempty(SET(no).Parent) - no = SET(no).Parent; -end - -%If straintagging initiated adjust LVupdated -if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') - SET(no).StrainTagging.LVupdated = 1; -end - -%Setup -[x,y,slice] = getclickedcoords; -%extra safety check -if slice>SET(NO).ZSize - slice=SET(NO).CurrentSlice; -end - -switch type - case 'endo' - if isempty(SET(no).EndoInterpX) - return; - end; - temp = SET(no).EndoInterpX{SET(no).CurrentTimeFrame,slice}; - if isempty(temp) - return - end - temp(DATA.Pin,1) = y; %Make sure column vector - SET(no).EndoInterpX{SET(no).CurrentTimeFrame,slice} = temp; - temp = SET(no).EndoInterpY{SET(no).CurrentTimeFrame,slice}; - temp(DATA.Pin,1) = x; - SET(no).EndoInterpY{SET(no).CurrentTimeFrame,slice} = temp; - if ~isempty(SET(no).EndoX)&&... - ~all(isnan(SET(no).EndoX(:,SET(no).CurrentTimeFrame,slice))) - [xout,yout] = interphelper(... - SET(no).EndoInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).EndoInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).EndoX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).EndoY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - end - case 'epi' - if isempty(SET(no).EpiInterpX) - return; - end; - temp = SET(no).EpiInterpX{SET(no).CurrentTimeFrame,slice}; - if isempty(temp) - return - end - temp(DATA.Pin,1) = y; - SET(no).EpiInterpX{SET(no).CurrentTimeFrame,slice} = temp; - temp = SET(no).EpiInterpY{SET(no).CurrentTimeFrame,slice}; - temp(DATA.Pin,1) = x; - SET(no).EpiInterpY{SET(no).CurrentTimeFrame,slice} = temp; - if ~isempty(SET(no).EpiX)&&... - ~all(isnan(SET(no).EpiX(:,SET(no).CurrentTimeFrame,slice))) - [xout,yout] = interphelper(... - SET(no).EpiInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).EpiInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).EpiX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).EpiY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - end - case 'rvendo' - if isempty(SET(no).RVEndoInterpX) - return; - end; - temp = SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,slice}; - if isempty(temp) - return - end - temp(DATA.Pin,1) = y; - SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,slice} = temp; - temp = SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,slice}; - temp(DATA.Pin,1) = x; - SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,slice} = temp; - if ~isempty(SET(no).RVEndoX)&&... - ~all(isnan(SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) - [xout,yout] = interphelper(... - SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - end - case 'rvepi' - if isempty(SET(no).RVEpiInterpX) - return; - end; - temp = SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,slice}; - if isempty(temp) - return - end - temp(DATA.Pin,1) = y; - SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,slice} = temp; - temp = SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,slice}; - temp(DATA.Pin,1) = x; - SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,slice} = temp; - if ~isempty(SET(no).RVEpiX)&&... - ~all(isnan(SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,slice))) - [xout,yout] = interphelper(... - SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,slice},... - SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,slice}); - if ~isempty(xout) - SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,slice) = xout; - SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,slice) = yout; - end - end -end; - -if ~all(strcmp(DATA.ViewPanelsType(DATA.ViewPanels == no),'one')) - updatemodeldisplay; -end -drawfunctions('drawsliceno'); - -%------------------------------------ -function scale_Buttondown(type,panel) %#ok -%------------------------------------ -%Button down function for scaling of objects / contours. -global DATA SET NO - -if nargin<1 - return; -end; - -if nargin<2 - panel = DATA.CurrentPanel; -end; - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -[~,~,slice] = getclickedcoords; -% If slice has changed, make sure montage/one are in sync -if (slice>SET(no).ZSize) - return; -end -switchtoslice(slice); - -tools('enableundo') -switchtopanel(panel); - -[DATA.CursorYOfs,DATA.CursorXOfs] = calcfunctions('calcoffset',slice,[],no,panel); - -switch get(DATA.imagefig,'SelectionType') - case 'alt' - return; - case 'normal' - switch type - case 'image' - return; - case 'endo' - if isempty(SET(no).EndoX) - myfailed('No LV endocardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).EndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).EndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','r'); - case 'epi' - if isempty(SET(no).EpiX) - myfailed('No LV epicardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','g'); - case 'rvendo' - if isempty(SET(no).RVEndoX) - myfailed('No RV endocardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','m'); - case 'rvepi' - if isempty(SET(no).RVEpiX) - myfailed('No RV epicardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','c'); - case 'roi' - %Find closest ROI - - if SET(no).RoiN<1 - myfailed('No ROIs available.',DATA.GUI.Segment); - return; - end; - - [ycl,xcl] = getclickedcoords; - mindist = 1e10; - n = NaN; - for loop=1:SET(no).RoiN - if ~isempty(find(SET(no).Roi(loop).Z==SET(no).CurrentSlice,1))&&... - ~isempty(find(SET(no).Roi(loop).T==SET(no).CurrentTimeFrame,1)) - xr = SET(no).Roi(loop).X(:,SET(no).CurrentTimeFrame); - yr = SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame); - thisdist = min(sqrt((xr-xcl).^2+(yr-ycl).^2)); - if thisdist -%--------------------------- -%Motion function for scaling. -persistent startslice startrad -global DATA SET NO - -if nargin==1 - startrad = []; - return; -end; - -if isempty(startrad) - - %Get coordinate - [starty,startx,startslice] = getclickedcoords; - - mx = mean(DATA.CursorX); - my = mean(DATA.CursorY); - - startrad = sqrt((mx-startx).^2+(my-starty).^2); - -end - -%Get coordinate -[y,x,slice] = getclickedcoords; - -mx = mean(DATA.CursorX); -my = mean(DATA.CursorY); - -rad = sqrt((mx-x).^2+(my-y).^2); -f = rad/startrad; - -%If different slice then buttonup -if (slice~=startslice) ... - || (~isempty(DATA.CursorX) && ... - (any((mx+(DATA.CursorX-mx)*f)<0.5)||any((mx+(DATA.CursorX-mx)*f)>SET(NO).YSize))) ... - || (~isempty(DATA.CursorY) && ... - (any((my+(DATA.CursorY-my)*f)<0.5)||any((my+(DATA.CursorY-my)*f)>SET(NO).XSize))) - scale_Buttonup('abort'); -end; - -set(DATA.Handles.cursor(DATA.CurrentPanel),... - 'ydata',mx+DATA.CursorYOfs+(DATA.CursorX-mx)*f,... - 'xdata',my+DATA.CursorXOfs+(DATA.CursorY-my)*f); - -%---------------------------- -function scale_Buttonup(type) -%---------------------------- -%Button up function for scaling -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -DATA.buttonup_Callback; -set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''buttonup_Callback'')','segment')); -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - -% if strcmp(DATA.ProgramName,'Segment CMR') -% DATA.ThisFrameOnly = true; -% end -if DATA.ThisFrameOnly && ~strcmp(type,'roi') - tf = SET(no).CurrentTimeFrame; -else - tf = 1:SET(no).TSize; -end; - -slice = SET(no).StartSlice:SET(no).EndSlice; - -%Extract the current data -x = get(DATA.Handles.cursor(DATA.CurrentPanel),'ydata')-DATA.CursorYOfs; -y = get(DATA.Handles.cursor(DATA.CurrentPanel),'xdata')-DATA.CursorXOfs; - -x = x(1); %one point is enough -y = y(1); - -%Find mean (same for both since scaling) -mx = mean(DATA.CursorX); -my = mean(DATA.CursorY); - -startrad = sqrt((mx-DATA.CursorX(1)).^2+(my-DATA.CursorY(1)).^2); -rad = sqrt((mx-x).^2+(my-y).^2); - -%Calculate factor -f = rad/startrad; -pinwarn=false; -switch type - case 'endo' - SET(no).EndoX(:,tf,slice) = mx+f*(SET(no).EndoX(:,tf,slice)-mx); - SET(no).EndoY(:,tf,slice) = my+f*(SET(no).EndoY(:,tf,slice)-my); - if ~isempty(SET(no).EndoPinX) - [SET(no).EndoPinX,SET(no).EndoPinY,pinwarn]=pinresize(... - SET(no).EndoPinX,SET(no).EndoPinY,tf,slice,[mx my],f); - end - if ~isempty(SET(no).EndoInterpX) - [SET(no).EndoInterpX,SET(no).EndoInterpY,pinwarn]=pinresize(... - SET(no).EndoInterpX,SET(no).EndoInterpY,tf,slice,[mx my],f); - end - case 'epi' - SET(no).EpiX(:,tf,slice) = mx+f*(SET(no).EpiX(:,tf,slice)-mx); - SET(no).EpiY(:,tf,slice) = my+f*(SET(no).EpiY(:,tf,slice)-my); - if ~isempty(SET(no).EpiPinX) - [SET(no).EpiPinX,SET(no).EpiPinY,pinwarn]=pinresize(... - SET(no).EpiPinX,SET(no).EpiPinY,tf,slice,[mx my],f); - end - if ~isempty(SET(no).EpiInterpX) - [SET(no).EpiInterpX,SET(no).EpiInterpY,pinwarn]=pinresize(... - SET(no).EpiInterpX,SET(no).EpiInterpY,tf,slice,[mx my],f); - end - case 'rvendo' - SET(no).RVEndoX(:,tf,slice) = mx+f*(SET(no).RVEndoX(:,tf,slice)-mx); - SET(no).RVEndoY(:,tf,slice) = my+f*(SET(no).RVEndoY(:,tf,slice)-my); - if ~isempty(SET(no).RVEndoPinX) - [SET(no).RVEndoPinX,SET(no).RVEndoPinY,pinwarn]=pinresize(... - SET(no).RVEndoPinX,SET(no).RVEndoPinY,tf,slice,[mx my],f); - end - if ~isempty(SET(no).RVEndoInterpX) - [SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,pinwarn]=pinresize(... - SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,tf,slice,[mx my],f); - end - case 'rvepi' - SET(no).RVEpiX(:,tf,slice) = mx+f*(SET(no).RVEpiX(:,tf,slice)-mx); - SET(no).RVEpiY(:,tf,slice) = my+f*(SET(no).RVEpiY(:,tf,slice)-my); - if ~isempty(SET(no).RVEpiPinX) - [SET(no).RVEpiPinX,SET(no).RVEpiPinY,pinwarn]=pinresize(... - SET(no).RVEpiPinX,SET(no).RVEpiPinY,tf,slice,[mx my],f); - end - if ~isempty(SET(no).RVEpiInterpX) - [SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,pinwarn]=pinresize(... - SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,tf,slice,[mx my],f); - end - case 'roi' - SET(no).Roi(SET(no).RoiCurrent).X(:,tf) = mx+f*(SET(no).Roi(SET(no).RoiCurrent).X(:,tf)-mx); - SET(no).Roi(SET(no).RoiCurrent).Y(:,tf) = my+f*(SET(no).Roi(SET(no).RoiCurrent).Y(:,tf)-my); - roi('roiforceapply'); %ensure that all rois are equal size if this option is checked. - [~,SET(no).Roi(SET(no).RoiCurrent).Area] = ... - calcfunctions('calcroiarea',no,SET(no).RoiCurrent); - [m,sd]=calcfunctions('calcroiintensity',no,SET(no).RoiCurrent); - SET(no).Roi(SET(no).RoiCurrent).Mean = m; - SET(no).Roi(SET(no).RoiCurrent).StD = sd; - - if ~isempty(DATA.FlowNO) && ismember(DATA.FlowNO,SET(no).Linked) && ~isempty(DATA.FlowROI) - if SET(no).RoiN <1 - DATA.FlowROI = []; - else - calcfunctions('calcflow',no); - end - end - - DATA.updateaxestables('area',no); - - case 'abort' - beep; - DATA.CursorX = []; - DATA.CursorY = []; - scale_Motion('reset'); - set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - return; -end; - -if (pinwarn) - mywarning('Pins moved outside frame deleted.',DATA.GUI.Segment); -end - -%updatemodeldisplay(no); -%drawimagepanel; -%set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - -%Reset -DATA.CursorX = []; -DATA.CursorY = []; -scale_Motion('reset'); - -updatemodeldisplay; -drawfunctions('drawallslices'); - -updatevolume; -DATA.updateaxestables('t2star'); - - -%------------------------------------------- - function state = iconson(name) - %------------------------------------------ - %if given name of button return state if run with no input returns - %states of all buttons. if given cell with multiple button return icons - %in order of request. - global DATA - - state=0; - icons=[DATA.Handles.permanenticonholder.iconCell{:},DATA.Icons.lviconcell{:},DATA.Icons.rviconcell{:},DATA.Icons.roiflowiconcell{:},DATA.Icons.viabilityiconcell{:},... - DATA.Icons.analysisiconcell{:}, DATA.Icons.imageiconcell{:},DATA.Icons.hidecell{:}]; - N=length(icons); - if nargin==1 - %return icon state - if ~iscell(name) - ind=find(strcmp(name,{icons.name})); - if length(ind)>1 - ind=ind(1); - end - - if isempty(ind) - state={0,nan}; - else - state={icons(ind).isindented,icons(ind)}; - end - - else - n=length(name); - state=cell(n,2); - %Get all icons and states for names in cell - counter=1; - indlist=zeros(1,n); - for i=1:n - ind=find(strcmp(name(i),{icons.name})); - - if isempty(ind) - ind=nan; - end - - if length(ind)>1 - ind=ind(1); - end - - indlist(i)=ind; - end - - for i=1:n - if isnan(indlist(i)) - state{i,1} = 0; - state{i,2} = nan; - else - state{i,1} = icons(indlist(i)).isindented; - state{i,2} = icons(indlist(i)); - end - end - end - else - state=cell(N,2); - for i=1:N - state{i,1} = icons{i}.name; - state{i,2} = icons{i}.isindented; - end - end - - -%------------------------------------ -function dragepi_Buttondown(type,panel) %#ok -%------------------------------------ -%Button down function for scaling of objects / contours. -global DATA SET NO - -if nargin<1 - return; -end; - -if nargin<2 - panel = DATA.CurrentPanel; -end; - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -[~,~,slice] = getclickedcoords; -% If slice has changed, make sure montage/one are in sync -if (slice>SET(no).ZSize) - return; -end -switchtoslice(slice); - -tools('enableundo') -switchtopanel(panel); - -[DATA.CursorYOfs,DATA.CursorXOfs] = calcfunctions('calcoffset',slice,[],no,panel); - -switch get(DATA.imagefig,'SelectionType') - case 'alt' - return; - case 'normal' - switch type - case 'image' - return; - case {'one','allslices'} - if isempty(SET(no).EpiX) - myfailed('No LV epicardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).EpiX(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - y = SET(no).EpiY(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','g'); - end - otherwise - return; -end; - -DATA.CursorX = x; -DATA.CursorY = y; -set(DATA.Handles.cursor(DATA.CurrentPanel),... - 'xdata',DATA.CursorY+DATA.CursorXOfs,... - 'ydata',DATA.CursorX+DATA.CursorYOfs,... - 'visible','on'); - -set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('segment(''dragepi_Buttonup'',''%s'')',type)); -motionfcn = ['segment(''dragepi_Motion'');' get(DATA.imagefig,'WindowButtonMotionFcn')]; -set(DATA.imagefig,'WindowButtonMotionFcn',motionfcn); - -%--------------------------- -function dragepi_Motion(reset) %#ok -%--------------------------- -%Motion function for scaling. -persistent startslice startrad -global DATA SET NO - -if nargin==1 - startrad = []; - return; -end; - -if isempty(startrad) - %Get coordinate - [starty,startx,startslice] = getclickedcoords; - mx = mean(DATA.CursorX); - my = mean(DATA.CursorY); - startrad = sqrt((mx-startx).^2+(my-starty).^2); -end - -%Get coordinate -[y,x,slice] = getclickedcoords; - -mx = mean(DATA.CursorX); -my = mean(DATA.CursorY); - -rad = sqrt((mx-x).^2+(my-y).^2); -f = rad/startrad; - -%If different slice then buttonup -if (slice~=startslice) ... - || (~isempty(DATA.CursorX) && ... - (any((mx+(DATA.CursorX-mx)*f)<0.5)||any((mx+(DATA.CursorX-mx)*f)>SET(NO).YSize))) ... - || (~isempty(DATA.CursorY) && ... - (any((my+(DATA.CursorY-my)*f)<0.5)||any((my+(DATA.CursorY-my)*f)>SET(NO).XSize))) - dragepi_Buttonup('abort'); -end; - -set(DATA.Handles.cursor(DATA.CurrentPanel),... - 'ydata',mx+DATA.CursorYOfs+(DATA.CursorX-mx)*f,... - 'xdata',my+DATA.CursorXOfs+(DATA.CursorY-my)*f); - -%---------------------------- -function dragepi_Buttonup(type) -%---------------------------- -%Button up function for scaling -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -DATA.buttonup_Callback; -set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''buttonup_Callback'')','segment')); -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - -tf = SET(no).CurrentTimeFrame; - -%Extract the current data -x = get(DATA.Handles.cursor(DATA.CurrentPanel),'ydata')-DATA.CursorYOfs; -y = get(DATA.Handles.cursor(DATA.CurrentPanel),'xdata')-DATA.CursorXOfs; - -x = x(1); %one point is enough -y = y(1); - -%Find mean (same for both since scaling) -mx = mean(DATA.CursorX); -my = mean(DATA.CursorY); - -startrad = sqrt((mx-DATA.CursorX(1)).^2+(my-DATA.CursorY(1)).^2); -rad = sqrt((mx-x).^2+(my-y).^2); - -%Calculate factor -f = rad/startrad; -meanres = mean([SET(no).ResolutionX, SET(no).ResolutionY]); -%expand the epicardium (not in the outflow tract (wallthickness = 0 in the 30% most basal LV slices)) -switch type - case {'one','allslices'} - switch type - case 'one' - slices = SET(no).CurrentSlice; - case 'allslices' - startslice = find(~isnan(SET(no).EpiX(1,tf,:)),1,'first'); - endslice = find(~isnan(SET(no).EpiX(1,tf,:)),1,'last'); - slices = startslice:endslice; - if length(slices) > 2 - mostbasalslice = startslice+0.3*length(slices); - else - mostbasalslice = endslice; - end - end - for slice = slices - %calculate wallthickness - switch type - case 'one' - dowallthickness = existfunctions('existendoinselected',no,tf,slice); - case 'allslices' - dowallthickness = (existfunctions('existendoinselected',no,tf,slice) && slice < mostbasalslice); - end - if dowallthickness - wallthickness = nan(1,length(SET(no).EpiX(:,tf,slice))); - for zloop = 1:length(SET(no).EpiX(:,tf,slice)) - tempwallthickness = sqrt(... - (SET(no).EpiX(zloop,tf,slice)-SET(no).EndoX(:,tf,slice)).^2+ ... - (SET(no).EpiY(zloop,tf,slice)-SET(no).EndoY(:,tf,slice)).^2); - wallthickness(zloop) = min(tempwallthickness); - end - isnotoutflowtract = find(wallthickness>(1/meanres)); - else - isnotoutflowtract = 1:length(SET(no).EpiX(:,tf,slice)); - end - - %shrink/expand epi - mx = mean(SET(no).EpiX(:,tf,slice)); - my = mean(SET(no).EpiY(:,tf,slice)); - SET(no).EpiX(isnotoutflowtract,tf,slice) = mx+f*(SET(no).EpiX(isnotoutflowtract,tf,slice)-mx); - SET(no).EpiY(isnotoutflowtract,tf,slice) = my+f*(SET(no).EpiY(isnotoutflowtract,tf,slice)-my); - end - case 'abort' - beep; - DATA.CursorX = []; - DATA.CursorY = []; - dragepi_Motion('reset'); - set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - return; -end; - -%Reset -DATA.CursorX = []; -DATA.CursorY = []; -dragepi_Motion('reset'); - -updatemodeldisplay; -drawfunctions('drawallslices');%was drawsliceno but changed in order to update intersectionpoints -updatevolume; -DATA.updateaxestables('t2star'); - - -%------------------ -function rotatetemp(alpha) %#ok -%------------------ -%This function should late be replaced with qa tool that rotates objects, -%just as scale and move does. - -global NO SET - -if nargin==0 - alpha = 10; -end; - -x = SET(NO).EndoX(:,:,SET(NO).CurrentSlice); -y = SET(NO).EndoY(:,:,SET(NO).CurrentSlice); -mx = mean(x(:)); -my = mean(y(:)); - -%Translate to origo -x = x - mx; -y = y - my; - -%Define rotation -alpha = alpha/180*pi; %from degrees -sinalpha = sin(alpha); -cosalpha = cos(alpha); - -%Rotate -xnew = x*cosalpha+y*sinalpha; -ynew = -x*sinalpha+y*cosalpha; - -%Translage back -xnew = xnew + mx; -ynew = ynew + my; - -SET(NO).EndoX(:,:,SET(NO).CurrentSlice) = xnew; -SET(NO).EndoY(:,:,SET(NO).CurrentSlice) = ynew; - -updatemodeldisplay; - -drawfunctions('drawallslices');%was drawsliceno but changed in order to update intersectionpoints - -%----------------------------------- -function move_Buttondown(type,panel) %#ok -%----------------------------------- -%Button down function for moving / translating objects / contours. -global DATA SET NO - -if nargin<1 - type = 'image'; -end; - -if nargin<2 - panel=DATA.CurrentPanel; -end; - -switchtopanel(panel); - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -selectiontype = get(DATA.imagefig,'SelectionType'); -switch selectiontype - case 'alt' - DATA.contextmenu; - case 'normal' - %--- Normal click - [y,x,slice] = getclickedcoords; - % If slice has changed, make sure montage/one are in sync - if (slice>SET(no).ZSize) - return; - end - if ~isempty(SET(no).StartSlice) - if slice < SET(no).StartSlice || slice > SET(no).EndSlice - switchtoslice(slice); - end - end; - tools('enableundo') - - [DATA.CursorYOfs,DATA.CursorXOfs] = calcfunctions('calcoffset',slice,[],no,panel); - - %Called when clicked on an object and move tool. - switch type - case 'endo' - if isempty(SET(no).EndoX) - myfailed('No LV endocardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).EndoX(:,SET(no).CurrentTimeFrame,slice); - y = SET(no).EndoY(:,SET(no).CurrentTimeFrame,slice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','r'); - case 'epi' - if isempty(SET(no).EpiX) - myfailed('No LV epicardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).EpiX(:,SET(no).CurrentTimeFrame,slice); - y = SET(no).EpiY(:,SET(no).CurrentTimeFrame,slice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','g'); - case 'rvendo' - if isempty(SET(no).RVEndoX) - myfailed('No RV endocardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,slice); - y = SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,slice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','m'); - case 'rvepi' - if isempty(SET(no).RVEpiX) - myfailed('No RV epicardium available.',DATA.GUI.Segment); - return; - end; - x = SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,slice); - y = SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,slice); - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','c'); - case 'allseg' - - case 'roi' - %Find closest ROI - if SET(no).RoiN<1 - myfailed('No ROIs available.',DATA.GUI.Segment); - return; - end; - - mindist = 1e10; - n = NaN; - for loop=1:SET(no).RoiN - if ~isempty(find(SET(no).Roi(loop).Z==slice,1))&& ... - ~isempty(find(SET(no).Roi(loop).T==SET(no).CurrentTimeFrame,1)) - xr = SET(no).Roi(loop).X(:,SET(no).CurrentTimeFrame); - yr = SET(no).Roi(loop).Y(:,SET(no).CurrentTimeFrame); - thisdist = min(sqrt((xr-x).^2+(yr-y).^2)); - if thisdist -%-------------------------- -%Motion function for moving / translating objects / contours. -persistent startx starty startslice -global DATA SET NO - -if (nargin==1) - startx = []; - starty = []; -end; - -if isempty(startx) - %Get coordinate - [starty,startx,startslice] = getclickedcoords; -else - %Get coordinate - [y,x,slice] = getclickedcoords; - %If different slice then buttonup - if (slice~=startslice) ... - || (isempty(DATA.CursorX) && ... - (any((DATA.CursorX-startx+x)<0.5)||any((DATA.CursorX-startx+x)>SET(NO).YSize))) ... - || (isempty(DATA.CursorY) && ... - (any((DATA.CursorY-starty+y)<0.5)||any((DATA.CursorY-starty+y)>SET(NO).XSize))) - move_Buttonup('abort'); - end; - if nargin==0 - if (slice~=startslice) - move_Buttonup('abort'); - end; - end; - -set(DATA.Handles.cursor(DATA.CurrentPanel),... - 'ydata',DATA.CursorYOfs+DATA.CursorX-startx+x,... - 'xdata',DATA.CursorXOfs+DATA.CursorY-starty+y); - %set(DATA.Handles.cursor(DATA.CurrentPanel),... - % 'ydata',DATA.CursorYOfs+DATA.CursorX-startx+x,... - % 'xdata',DATA.CursorXOfs+DATA.CursorY-starty+y); -end; - -%--------------------------- -function move_Buttonup(type) -%--------------------------- -%Button up function for moving functions. -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -DATA.buttonup_Callback; -set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''buttonup_Callback'')','segment')); -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - -%Extract the data -x = get(DATA.Handles.cursor(DATA.CurrentPanel),'ydata')-DATA.CursorYOfs; -y = get(DATA.Handles.cursor(DATA.CurrentPanel),'xdata')-DATA.CursorXOfs; - -%Calculate displacement -dx = mean(x)-mean(DATA.CursorX); -dy = mean(y)-mean(DATA.CursorY); - -% if strcmp(DATA.ProgramName,'Segment CMR') -% DATA.ThisFrameOnly = true; -% end -if DATA.ThisFrameOnly %&& ~strcmp(type, 'roi') - tf = SET(no).CurrentTimeFrame; -else - tf = 1:SET(no).TSize; -end; - -slice = SET(no).StartSlice:SET(no).EndSlice; -pinwarn=false; -switch type - case 'endo' - SET(no).EndoX(:,tf,slice) = SET(no).EndoX(:,tf,slice)+dx; - SET(no).EndoY(:,tf,slice) = SET(no).EndoY(:,tf,slice)+dy; - if ~isempty(SET(no).EndoPinX) - [SET(no).EndoPinX,SET(no).EndoPinY,pinwarn]=pinresize(... - SET(no).EndoPinX,SET(no).EndoPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).EndoInterpX) - [SET(no).EndoInterpX,SET(no).EndoInterpY,pinwarn]=pinresize(... - SET(no).EndoInterpX,SET(no).EndoInterpY,tf,slice,[dx dy]); - end - case 'epi' - SET(no).EpiX(:,tf,slice) = SET(no).EpiX(:,tf,slice)+dx; - SET(no).EpiY(:,tf,slice) = SET(no).EpiY(:,tf,slice)+dy; - if ~isempty(SET(no).EpiPinX) - [SET(no).EpiPinX,SET(no).EpiPinY,pinwarn]=pinresize(... - SET(no).EpiPinX,SET(no).EpiPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).EpiInterpX) - [SET(no).EpiInterpX,SET(no).EpiInterpY,pinwarn]=pinresize(... - SET(no).EpiInterpX,SET(no).EpiInterpY,tf,slice,[dx dy]); - end - case 'rvendo' - SET(no).RVEndoX(:,tf,slice) = SET(no).RVEndoX(:,tf,slice)+dx; - SET(no).RVEndoY(:,tf,slice) = SET(no).RVEndoY(:,tf,slice)+dy; - if ~isempty(SET(no).RVEndoPinX) - [SET(no).RVEndoPinX,SET(no).RVEndoPinY,pinwarn]=pinresize(... - SET(no).RVEndoPinX,SET(no).RVEndoPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).RVEndoInterpX) - [SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,pinwarn]=pinresize(... - SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,tf,slice,[dx dy]); - end - case 'rvepi' - SET(no).RVEpiX(:,tf,slice) = SET(no).RVEpiX(:,tf,slice)+dx; - SET(no).RVEpiY(:,tf,slice) = SET(no).RVEpiY(:,tf,slice)+dy; - if ~isempty(SET(no).RVEpiPinX) - [SET(no).RVEpiPinX,SET(no).RVEpiPinY,pinwarn]=pinresize(... - SET(no).RVEpiPinX,SET(no).RVEpiPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).RVEpiInterpX) - [SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,pinwarn]=pinresize(... - SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,tf,slice,[dx dy]); - end - case 'roi' - SET(no).Roi(SET(no).RoiCurrent).X(:,tf) = SET(no).Roi(SET(no).RoiCurrent).X(:,tf)+dx; - SET(no).Roi(SET(no).RoiCurrent).Y(:,tf) = SET(no).Roi(SET(no).RoiCurrent).Y(:,tf)+dy; - roi('roiforceapply'); %ensure that all rois are equal size if this option is checked. - [m,sd]=calcfunctions('calcroiintensity',no,SET(no).RoiCurrent); - SET(no).Roi(SET(no).RoiCurrent).Mean = m; - SET(no).Roi(SET(no).RoiCurrent).StD = sd; - %update flow result panel - if ~isempty(DATA.FlowNO) && ismember(DATA.FlowNO,SET(no).Linked) && ~isempty(DATA.FlowROI) - if SET(no).RoiN <1 - DATA.FlowROI = []; - else - calcfunctions('calcflow',no); - end - end - DATA.updateaxestables('area',no); - case 'abort' - beep; - DATA.CursorX = []; - DATA.CursorY = []; - set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - return; - %myfailed('You can not translate between slices. Aborted.',DATA.GUI.Segment); -end; - -if (pinwarn) - mywarning('Pins moved outside frame deleted.',DATA.GUI.Segment); -end - -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); -updatemodeldisplay; -drawfunctions('drawallslices');% was drawsliceno but changed in order to update intersection points -updatevolume; -DATA.updateaxestables('t2star'); - -%Reset -DATA.CursorX = []; -DATA.CursorY = []; - - -%----------------------------------- -function moveall_Buttondown(type,panel) %#ok -%----------------------------------- -%Button down function for moving / translating all objects / contours. -global DATA SET NO - -if nargin<1 - type = 'image'; -end; - -if nargin<2 - panel=DATA.CurrentPanel; -end; - -switchtopanel(panel); - -% statesandicons=segment('iconson',{'hidelv','hiderv'}); -% lvicon=statesandicons{1,2}; -% rvicon=statesandicons{2,2}; -% -% %trick that buttons are pressed -% lvicon.isindented=1; -% rvicon.isindented=1; -% -% %updatevisibility -% viewhiderv_Callback; -% viewhidelv_Callback; - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -selectiontype = get(DATA.imagefig,'SelectionType'); -switch selectiontype - case 'alt' - DATA.contextmenu; - case 'normal' - %--- Normal click - [y,x,slice] = getclickedcoords; - % If slice has changed, make sure montage/one are in sync - if (slice>SET(no).ZSize) - return; - end - if ~isempty(SET(no).StartSlice) - if slice < SET(no).StartSlice || slice > SET(no).EndSlice - switchtoslice(slice); - end - end; - tools('enableundo') - - [DATA.CursorYOfs,DATA.CursorXOfs] = calcfunctions('calcoffset',slice,[],no,panel); - x=[]; - y=[]; - if ~isempty(SET(no).EpiX) - x = [x;nan;SET(no).EpiX(:,SET(no).CurrentTimeFrame,slice)]; - y = [y;nan;SET(no).EpiY(:,SET(no).CurrentTimeFrame,slice)]; - end - - if ~isempty(SET(no).EndoX) - x = [x;nan;SET(no).EndoX(:,SET(no).CurrentTimeFrame,slice)]; - y = [y;nan;SET(no).EndoY(:,SET(no).CurrentTimeFrame,slice)]; - end - - if ~isempty(SET(no).RVEndoX) - x = [x;nan;SET(no).RVEndoX(:,SET(no).CurrentTimeFrame,slice)]; - y = [y;nan;SET(no).RVEndoY(:,SET(no).CurrentTimeFrame,slice)]; - end - - if ~isempty(SET(no).RVEpiX) - x = [x;nan;SET(no).RVEpiX(:,SET(no).CurrentTimeFrame,slice)]; - y = [y;nan;SET(no).RVEpiY(:,SET(no).CurrentTimeFrame,slice)]; - end - set(DATA.Handles.cursor(DATA.CurrentPanel),'color','w'); - - %generellt - DATA.CursorX = x; - DATA.CursorY = y; - move_Motion('reset'); - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('segment(''moveall_Buttonup'',''%s'')',type)); - motionfcn = 'segment(''move_Motion'');'; %get(DATA.imagefig,'WindowButtonMotionFcn')]; - set(DATA.imagefig,'WindowButtonMotionFcn',motionfcn); - - set(DATA.Handles.cursor(DATA.CurrentPanel),... - 'xdata',DATA.CursorY+DATA.CursorXOfs,... - 'ydata',DATA.CursorX+DATA.CursorYOfs,... - 'visible','on'); - otherwise - return; %case 'open', 'extended' -end; - - -%-------------------------- -function moveall_Motion(reset) %#ok -%-------------------------- -%Motion function for moving / translating all objects / contours. -persistent startx starty startslice -global DATA SET NO - -no = NO; -if (nargin==1) - startx = []; - starty = []; -end; - -if isempty(startx) - %Get coordinate - [starty,startx,startslice] = getclickedcoords; -else - %Get coordinate - [y,x,slice] = getclickedcoords; - - %If different slice then buttonup - if (slice~=startslice) ... - || (isempty(DATA.CursorX) && ... - (any((DATA.CursorX-startx+x)<0.5)||any((DATA.CursorX-startx+x)>SET(NO).YSize))) ... - || (isempty(DATA.CursorY) && ... - (any((DATA.CursorY-starty+y)<0.5)||any((DATA.CursorY-starty+y)>SET(NO).XSize))) - moveall_Buttonup('abort'); - end; - if nargin==0 - if (slice~=startslice) - moveall_Buttonup('abort'); - end; - end; - - dx =x-startx;% mean(x)-mean(DATA.CursorX); - dy =y-starty;%mean(y)-mean(DATA.CursorY); -% - tools('translatecontours',dx,dy); - %set(DATA.Handles.cursor(DATA.CurrentPanel),... - % 'ydata',DATA.CursorYOfs+DATA.CursorX-startx+x,... - % 'xdata',DATA.CursorXOfs+DATA.CursorY-starty+y); -end; -% x = get(DATA.Handles.cursor(DATA.CurrentPanel),'ydata')-DATA.CursorYOfs; -% y = get(DATA.Handles.cursor(DATA.CurrentPanel),'xdata')-DATA.CursorXOfs; -% % -% dx =x-startx;% mean(x)-mean(DATA.CursorX); -% dy =y-starty;%mean(y)-mean(DATA.CursorY); -% % -% tools('translatecontours',dx,dy); - -% if strcmp(DATA.ProgramName,'Segment CMR') -% DATA.ThisFrameOnly = true; -% end -% if DATA.ThisFrameOnly -% tf = SET(no).CurrentTimeFrame; -% else -% tf = 1:SET(no).TSize; -% end; -% slice = SET(no).StartSlice:SET(no).EndSlice; -% pinwarn=false; -% %Extract the data -% x = get(DATA.Handles.cursor(DATA.CurrentPanel),'ydata')-DATA.CursorYOfs; -% y = get(DATA.Handles.cursor(DATA.CurrentPanel),'xdata')-DATA.CursorXOfs; -% %Calculate displacement -% dx = mean(x)-mean(DATA.CursorX); -% dy = mean(y)-mean(DATA.CursorY); -% disp(mean(x)), disp(mean(DATA.CursorX)) -% if ~isempty(SET(no).EndoX) && ~isnan(SET(no).EndoX(1,tf,slice)) -% SET(no).EndoX(:,tf,slice) = SET(no).EndoX(:,tf,slice)+dx; -% SET(no).EndoY(:,tf,slice) = SET(no).EndoY(:,tf,slice)+dy; -% if ~isempty(SET(no).EndoPinX) -% [SET(no).EndoPinX,SET(no).EndoPinY,pinwarn]=pinresize(... -% SET(no).EndoPinX,SET(no).EndoPinY,tf,slice,[dx dy]); -% end -% if ~isempty(SET(no).EndoInterpX) -% [SET(no).EndoInterpX,SET(no).EndoInterpY,pinwarn]=pinresize(... -% SET(no).EndoInterpX,SET(no).EndoInterpY,tf,slice,[dx dy]); -% end -% end -% if ~isempty(SET(no).EpiX) && ~isnan(SET(no).EpiX(1,tf,slice)) -% SET(no).EpiX(:,tf,slice) = SET(no).EpiX(:,tf,slice)+dx; -% SET(no).EpiY(:,tf,slice) = SET(no).EpiY(:,tf,slice)+dy; -% if ~isempty(SET(no).EpiPinX) -% [SET(no).EpiPinX,SET(no).EpiPinY,pinwarn]=pinresize(... -% SET(no).EpiPinX,SET(no).EpiPinY,tf,slice,[dx dy]); -% end -% if ~isempty(SET(no).EpiInterpX) -% [SET(no).EpiInterpX,SET(no).EpiInterpY,pinwarn]=pinresize(... -% SET(no).EpiInterpX,SET(no).EpiInterpY,tf,slice,[dx dy]); -% end -% end -% if ~isempty(SET(no).RVEndoX) && ~isnan(SET(no).RVEndoX(1,tf,slice)) -% SET(no).RVEndoX(:,tf,slice) = SET(no).RVEndoX(:,tf,slice)+dx; -% SET(no).RVEndoY(:,tf,slice) = SET(no).RVEndoY(:,tf,slice)+dy; -% if ~isempty(SET(no).RVEndoPinX) -% [SET(no).RVEndoPinX,SET(no).RVEndoPinY,pinwarn]=pinresize(... -% SET(no).RVEndoPinX,SET(no).RVEndoPinY,tf,slice,[dx dy]); -% end -% if ~isempty(SET(no).RVEndoInterpX) -% [SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,pinwarn]=pinresize(... -% SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,tf,slice,[dx dy]); -% end -% end -% if ~isempty(SET(no).RVEpiX) && ~isnan(SET(no).RVEpiX(1,tf,slice)) -% SET(no).RVEpiX(:,tf,slice) = SET(no).RVEpiX(:,tf,slice)+dx; -% SET(no).RVEpiY(:,tf,slice) = SET(no).RVEpiY(:,tf,slice)+dy; -% if ~isempty(SET(no).RVEpiPinX) -% [SET(no).RVEpiPinX,SET(no).RVEpiPinY,pinwarn]=pinresize(... -% SET(no).RVEpiPinX,SET(no).RVEpiPinY,tf,slice,[dx dy]); -% end -% if ~isempty(SET(no).RVEpiInterpX) -% [SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,pinwarn]=pinresize(... -% SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,tf,slice,[dx dy]); -% end -% end -% if SET(no).RoiN > 0 -% for roin = 1:SET(no).RoiN -% if ismember(SET(no).Roi(roin).Z,slice) -% SET(no).Roi(roin).X(:,tf) = SET(no).Roi(roin).X(:,tf)+dx; -% SET(no).Roi(roin).Y(:,tf) = SET(no).Roi(roin).Y(:,tf)+dy; -% roi('roiforceapply'); %ensure that all rois are equal size if this option is checked. -% [m,sd]=calcfunctions('calcroiintensity',no,SET(no).RoiCurrent); -% SET(no).Roi(roin).Mean = m; -% SET(no).Roi(roin).StD = sd; -% end -% end -% end -% -% if (pinwarn) -% mywarning('Pins moved outside frame deleted.',DATA.GUI.Segment); -% end - - -%set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); -%updatemodeldisplay; -%drawfunctions('drawallslices');% was drawsliceno but changed in order to update intersection points - -%--------------------------- -function moveall_Buttonup(type) -%--------------------------- -%Button up function for translating all objects / contours -global DATA SET NO - -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -% statesandicons=segment('iconson',{'hidelv','hiderv'}); -% lvicon=statesandicons{1,2}; -% rvicon=statesandicons{2,2}; -% -% %trick that buttons aren't pressed -% lvicon.isindented=0; -% rvicon.isindented=0; -% -% %updatevisibility -% viewhiderv_Callback; -% viewhidelv_Callback; - -DATA.buttonup_Callback; -set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''buttonup_Callback'')','segment')); -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - -%Extract the data -x = get(DATA.Handles.cursor(DATA.CurrentPanel),'ydata')-DATA.CursorYOfs; -y = get(DATA.Handles.cursor(DATA.CurrentPanel),'xdata')-DATA.CursorXOfs; - -%Calculate displacement -dx = nanmean(x)-nanmean(DATA.CursorX); -dy = nanmean(y)-nanmean(DATA.CursorY); - -% if strcmp(DATA.ProgramName,'Segment CMR') -% DATA.ThisFrameOnly = true; -% end -if DATA.ThisFrameOnly - tf = SET(no).CurrentTimeFrame; -else - tf = 1:SET(no).TSize; -end; - -slice = SET(no).StartSlice:SET(no).EndSlice; -pinwarn=false; - -switch type - case 'abort' - beep; - DATA.CursorX = []; - DATA.CursorY = []; - set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - return; - %myfailed('You can not translate between slices. Aborted.',DATA.GUI.Segment); - otherwise - if ~isempty(SET(no).EndoX) %&& all(~isnan(SET(no).EndoX(1,tf,slice))) - SET(no).EndoX(:,tf,slice) = SET(no).EndoX(:,tf,slice)+dx; - SET(no).EndoY(:,tf,slice) = SET(no).EndoY(:,tf,slice)+dy; - if ~isempty(SET(no).EndoPinX) - [SET(no).EndoPinX,SET(no).EndoPinY,pinwarn]=pinresize(... - SET(no).EndoPinX,SET(no).EndoPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).EndoInterpX) - [SET(no).EndoInterpX,SET(no).EndoInterpY,pinwarn]=pinresize(... - SET(no).EndoInterpX,SET(no).EndoInterpY,tf,slice,[dx dy]); - end - end - if ~isempty(SET(no).EpiX) %&& all(~isnan(SET(no).EpiX(1,tf,slice))) - SET(no).EpiX(:,tf,slice) = SET(no).EpiX(:,tf,slice)+dx; - SET(no).EpiY(:,tf,slice) = SET(no).EpiY(:,tf,slice)+dy; - if ~isempty(SET(no).EpiPinX) - [SET(no).EpiPinX,SET(no).EpiPinY,pinwarn]=pinresize(... - SET(no).EpiPinX,SET(no).EpiPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).EpiInterpX) - [SET(no).EpiInterpX,SET(no).EpiInterpY,pinwarn]=pinresize(... - SET(no).EpiInterpX,SET(no).EpiInterpY,tf,slice,[dx dy]); - end - end - if ~isempty(SET(no).RVEndoX) %&& all(~isnan(SET(no).RVEndoX(1,tf,slice))) - SET(no).RVEndoX(:,tf,slice) = SET(no).RVEndoX(:,tf,slice)+dx; - SET(no).RVEndoY(:,tf,slice) = SET(no).RVEndoY(:,tf,slice)+dy; - if ~isempty(SET(no).RVEndoPinX) - [SET(no).RVEndoPinX,SET(no).RVEndoPinY,pinwarn]=pinresize(... - SET(no).RVEndoPinX,SET(no).RVEndoPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).RVEndoInterpX) - [SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,pinwarn]=pinresize(... - SET(no).RVEndoInterpX,SET(no).RVEndoInterpY,tf,slice,[dx dy]); - end - end - if ~isempty(SET(no).RVEpiX) %&& all(~isnan(SET(no).RVEpiX(1,tf,slice))) - SET(no).RVEpiX(:,tf,slice) = SET(no).RVEpiX(:,tf,slice)+dx; - SET(no).RVEpiY(:,tf,slice) = SET(no).RVEpiY(:,tf,slice)+dy; - if ~isempty(SET(no).RVEpiPinX) - [SET(no).RVEpiPinX,SET(no).RVEpiPinY,pinwarn]=pinresize(... - SET(no).RVEpiPinX,SET(no).RVEpiPinY,tf,slice,[dx dy]); - end - if ~isempty(SET(no).RVEpiInterpX) - [SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,pinwarn]=pinresize(... - SET(no).RVEpiInterpX,SET(no).RVEpiInterpY,tf,slice,[dx dy]); - end - end - if SET(no).RoiN > 0 - for roin = 1:SET(no).RoiN - if ismember(SET(no).Roi(roin).Z,slice) - SET(no).Roi(roin).X(:,tf) = SET(no).Roi(roin).X(:,tf)+dx; - SET(no).Roi(roin).Y(:,tf) = SET(no).Roi(roin).Y(:,tf)+dy; - roi('roiforceapply'); %ensure that all rois are equal size if this option is checked. - [m,sd]=calcfunctions('calcroiintensity',no,SET(no).RoiCurrent); - SET(no).Roi(roin).Mean = m; - SET(no).Roi(roin).StD = sd; - end - end - if ~isempty(DATA.FlowNO) && ismember(DATA.FlowNO,SET(no).Linked) && ~isempty(DATA.FlowROI) - if SET(no).RoiN <1 - DATA.FlowROI = []; - else - calcfunctions('calcflow',no); - end - end - end -end; +%Interpolate, periodic boundaries +xout = interp1(d,reppinx,linspace(d(length(reppinx)/3+1),d(2*length(reppinx)/3+1),DATA.NumPoints),'pchip'); -if (pinwarn) - mywarning('Pins moved outside frame deleted.',DATA.GUI.Segment); -end +yout = interp1(d,reppiny,linspace(d(length(reppinx)/3+1),d(2*length(reppinx)/3+1),DATA.NumPoints),'pchip'); -if ~isempty(SET(no).StrainTagging) - SET(no).StrainTagging.LVupdated=1; -end +[xout,yout]=mypoly2cw(xout,yout); -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); -updatemodeldisplay; -drawfunctions('drawallslices');% was drawsliceno but changed in order to update intersection points -updatevolume; -DATA.updateaxestables('t2star'); +%----------------------------------------------- +function [x,y]=pointsfromcontour(X,Y,nbr_points) +%----------------------------------------------- +%select points from X,Y with probability higher +%when derivative magnitude in respect to distance to mass centre +%is large. -%Reset -DATA.CursorX = []; -DATA.CursorY = []; +% x_m=mean(X); +% y_m=mean(Y); +% r=sqrt((X-x_m).^2+(Y-y_m).^2); +% % +% p=[1;abs(diff(r))];%./sum(abs(diff(r))); +% % P=[0 cumsum(p)']; +% +% + ind=false(length(X),1); +ind(1:floor(length(X)/nbr_points):end)=true; +% ind(p(ind)<0.3)=false; +% s = rand('twister'); +% rand('twister',5489);%<-- semi random for now +% ran=rand(1,nbr_points); +% rand('twister',s); %<-random seed again +% +% nbr_points=floor(nbr_points/2); +% for i=1:nbr_points, +% ind(sum(ran(i) -%----------------------------------- -%Callback to put pins. -global DATA -switch type - case 'endo' - isendo = true; - dolv = true; - case 'epi' - isendo = false; - dolv = true; - case 'rvendo' - isendo = true; - dolv = false; -end; - -if dolv - %--- LV - if isendo - highlighttool(DATA.Tools.putendopin); - set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''endo'')',mfilename,panel)); - set(DATA.Handles.endocontour(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''endo'')',mfilename,panel)); - set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''endo'')',mfilename,panel)); - else - highlighttool(DATA.Tools.putepipin); - set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''epi'')',mfilename,panel)); - set(DATA.Handles.endocontour(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''epi'')',mfilename,panel)); - set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''epi'')',mfilename,panel)); - end; -else - %--- RV - if isendo - highlighttool(DATA.Tools.putrvendopin); - set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''rvendo'')',mfilename,panel)); - set(DATA.Handles.rvendocontour(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''rvendo'')',mfilename,panel)); - set(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('%s(''putpin_Buttondown'',%d,''rvendo'')',mfilename,panel)); - end; - -end; -%------------------------------------- -function putpin_Buttondown(panel,type) %#ok -%------------------------------------- -%Button down function for pins. -global DATA -switchtopanel(panel); +%------------------ +function rotatetemp(alpha) %#ok +%------------------ +%This function should late be replaced with qa tool that rotates objects, +%just as scale and move does. -switch get(DATA.imagefig,'SelectionType') - case 'normal' - %tools('enableundo') %called in doputpin_Callback(); - doputpin_Callback(type); - case 'alt' - %show menu - DATA.contextmenu; -end; +global NO SET -%-------------------- -function pin_Buttonup %#ok -%-------------------- -%Button up function for pins. -global DATA +if nargin==0 + alpha = 10; +end -checkconsistency; -set(DATA.imagefig,'WindowButtonMotionFcn',''); -updatemodeldisplay; -updatevolume; +x = SET(NO).EndoX(:,:,SET(NO).CurrentSlice); +y = SET(NO).EndoY(:,:,SET(NO).CurrentSlice); +mx = mean(x(:)); +my = mean(y(:)); -%------------------------ -function pin_Motion(type) %#ok -%------------------------ -%Motion function for pins. -global DATA SET NO +%Translate to origo +x = x - mx; +y = y - my; -[x,y,slice] = getclickedcoords; +%Define rotation +alpha = alpha/180*pi; %from degrees +sinalpha = sin(alpha); +cosalpha = cos(alpha); -switch type - case 'endo' - temp = SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice}; - temp(DATA.Pin) = y; - SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice} = temp; - temp = SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice}; - temp(DATA.Pin) = x; - SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice} = temp; - case 'epi' - temp = SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice}; - temp(DATA.Pin) = y; - SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice} = temp; - temp = SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice}; - temp(DATA.Pin) = x; - SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice} = temp; - case 'rvendo' - temp = SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice}; - temp(DATA.Pin) = y; - SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice} = temp; - temp = SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice}; - temp(DATA.Pin) = x; - SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice} = temp; -end - -updatemodeldisplay; -drawfunctions('drawsliceno'); +%Rotate +xnew = x*cosalpha+y*sinalpha; +ynew = -x*sinalpha+y*cosalpha; -%------------------------------ -function [PinX,PinY,pinwarn]=pinresize(PinX,PinY,tf,slice,mean,f) -%------------------------------ -%Helper function to move pins when resizing contours. -global SET NO +%Translage back +xnew = xnew + mx; +ynew = ynew + my; -%Use to point to mag data set -no = NO; -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; -end; - -mx=mean(1); -my=mean(2); -if (nargin<6) - f=1; - dx=0; - dy=0; -else - dx=mx; - dy=my; -end -pinwarn=false; +SET(NO).EndoX(:,:,SET(NO).CurrentSlice) = xnew; +SET(NO).EndoY(:,:,SET(NO).CurrentSlice) = ynew; -for tloop=tf - for zloop=slice - if ~isempty(PinX{tloop,zloop}) - PinX{tloop,zloop} = mx+f*(PinX{tloop,zloop}-dx); - PinY{tloop,zloop} = my+f*(PinY{tloop,zloop}-dy); - ind= (PinX{tloop,zloop}>0.5)... - &(PinY{tloop,zloop}>0.5)... - &(PinX{tloop,zloop} +function timebar_Motion %------------------------------ %Update current timeframe when user clicked in time bar graph. global DATA SET NO @@ -10347,26 +3380,14 @@ function pin_Motion(type) %#ok SET(NO).CurrentTimeFrame = 1+round(x/SET(NO).TIncr); SET(NO).CurrentTimeFrame = min(max(1,SET(NO).CurrentTimeFrame),SET(NO).TSize); -%update time bar line -t = SET(NO).TimeVector*1000; -set(DATA.Handles.timebar,'xdata',[t(SET(NO).CurrentTimeFrame) t(SET(NO).CurrentTimeFrame)],... - 'ydata',get(DATA.Handles.timebaraxes,'ylim')); - -%Update -% profile on; -% drawfunctions('drawsliceno'); -% profile report; - -nos = SET(NO).Linked; -%updatenopanels(NO) is performed in drawsliceno. - -%additional speed enhancement is that stateandicon is supplied from -%buttondown. However not sure if possible. -stateandicon=segment('iconson',{'hidescar','hidemar','hideall','play'}); -for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop),stateandicon); -end; +panels = find(ismember(DATA.ViewPanels,SET(NO).Linked)); +for p = panels + DATA.ViewIM{p} = []; + drawfunctions('drawpanel',p) +end +%update timebars +viewfunctions('updatetimebars') drawnow; %---------------------------------- @@ -10377,134 +3398,71 @@ function pin_Motion(type) %#ok if DATA.Interactionlock return; -end; +end %stateandicon=segment('iconson',{'hidescar','hidemar','hideall','play'}); %set(DATA.fig,'WindowButtonMotionFcn',@ segment_main.timebar_Motion(stateandicon)); set(DATA.fig,'WindowButtonMotionFcn',... sprintf('%s(''timebar_Motion'')',mfilename)); set(DATA.fig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); - -%------------------------------ -function timebarlv_Motion %#ok -%------------------------------ -%Update current timeframe when user clicked in volume graph. -global DATA SET NO - -[x] = mygetcurrentpoint(DATA.Handles.volumeaxes); -x = x/1000; - -%Find timeframe -SET(NO).CurrentTimeFrame = 1+round(x/SET(NO).TIncr); -SET(NO).CurrentTimeFrame = min(max(1,SET(NO).CurrentTimeFrame),SET(NO).TSize); - -%update time bar line -t = SET(NO).TimeVector*1000; -set(DATA.Handles.timebarlv,'xdata',[t(SET(NO).CurrentTimeFrame) t(SET(NO).CurrentTimeFrame)],... - 'ydata',get(DATA.Handles.volumeaxes,'ylim')); -%Update -drawfunctions('drawsliceno'); - -%---------------------------------- -function timebarlv_Buttondown %#ok -%---------------------------------- -%Button down function for the time bar in the volume graph. -global DATA NO - -if any(NO == DATA.LVNO) - if DATA.Interactionlock - return; - end; - - set(DATA.fig,'WindowButtonMotionFcn',... - sprintf('%s(''timebarlv_Motion'')',mfilename)); - set(DATA.fig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); -end - -%------------------------------ -function timebarflow_Motion %#ok -%------------------------------ -%Update current timeframe when user clicked in volume graph. -global DATA SET NO - -[x] = mygetcurrentpoint(DATA.Handles.flowaxes); -x = x/1000; - -%Find timeframe -SET(NO).CurrentTimeFrame = 1+round(x/SET(NO).TIncr); -SET(NO).CurrentTimeFrame = min(max(1,SET(NO).CurrentTimeFrame),SET(NO).TSize); -%update time bar line -t = SET(NO).TimeVector*1000; -set(DATA.Handles.timebarflow,'xdata',[t(SET(NO).CurrentTimeFrame) t(SET(NO).CurrentTimeFrame)],... - 'ydata',get(DATA.Handles.flowaxes,'ylim')); -%Update -nos = SET(NO).Linked; -for nloop=1:length(nos) - drawfunctions('updatenopanels',nos(nloop)); -end; -% drawfunctions('drawsliceno'); + sprintf('%s(''buttonup_Callback'')','buttonupfunctions')); -%---------------------------------- -function timebarflow_Buttondown %#ok -%---------------------------------- -%Button down function for the time bar in the volume graph. -global DATA SET NO +timebar_Motion -if NO == DATA.FlowNO || ismember(NO,SET(DATA.FlowNO).Linked) - if DATA.Interactionlock - return; - end; - - set(DATA.fig,'WindowButtonMotionFcn',... - sprintf('%s(''timebarflow_Motion'')',mfilename)); - set(DATA.fig,'WindowButtonUpFcn',... - sprintf('%s(''buttonup_Callback'')','segment')); -end %-------------------------------- function fasterframerate_Callback %#ok %-------------------------------- %Makes movie play faster -global SET%DATA SET +global DATA SET + +%First we need to pause the running by setting DATA.Run = 0; Then do a +%pause in the software so playing is taken down safely +wason = 0; +if DATA.Run + wason = 1; + undent(DATA.Handles.permanenticonholder,'play',0) + %pause(0.1) +end -%set(DATA.Handles.fasterframerateicon,'state','off'); ind = find(cat(1,SET(:).TSize)>1); if isempty(ind) ind = 1; -end; +end for no=ind' SET(no).BeatTime = SET(no).BeatTime*0.9; end -%DATA.StartTime = now; -%if ~DATA.Run - % playmovie_Callback; -%end; - +% if wason +% indent(DATA.Handles.permanenticonholder,'play',1) +% end %-------------------------------- function slowerframerate_Callback %#ok %-------------------------------- %Makes movie play slower -global SET%DATA SET +global DATA SET + +wason = 0; +if DATA.Run + wason = 1; + undent(DATA.Handles.permanenticonholder,'play',0) + %pause(0.1) +end -%set(DATA.Handles.slowerframerateicon,'state','off'); %If running make sure always update the first one. ind = find(cat(1,SET(:).TSize)>1); if isempty(ind) ind = 1; -end; +end for no=ind' SET(no).BeatTime = SET(no).BeatTime/0.9; end -%DATA.StartTime = now; -%if ~DATA.Run -% playmovie_Callback; -%end; +% if wason +% indent(DATA.Handles.permanenticonholder,'play',1) +% end %-------------- function ctrlc %#ok @@ -10523,11 +3481,11 @@ function pin_Motion(type) %#ok if nargout>0 varargout = cell(1,nargout); -end; +end if nargin<2 writetofile = false; -end; +end if not(writetofile) && ( (numel(outdata)<8000)||(nargout>0) ) stri = []; @@ -10540,14 +3498,14 @@ function pin_Motion(type) %#ok stri = [stri sprintf('true\t')]; %#ok else stri = [stri sprintf('false\t')]; %#ok - end; + end case {'uint8','int8','uint32'} stri = [stri sprintf('%d\t',temp)]; %#ok case {'double','single'} if length(temp)>1 myfailed('Vector not allowed in one cell.'); return; - end; + end if isempty(temp)||isnan(temp) stri = [stri sprintf('\t')]; %#ok else @@ -10555,8 +3513,8 @@ function pin_Motion(type) %#ok stri = [stri sprintf('\t')]; %#ok else stri = [stri sprintf('%f\t',temp)]; %#ok - end; - end; + end + end case 'char' %If a char has ascii 0 its a null char this might cause trouble %for export. @@ -10569,23 +3527,23 @@ function pin_Motion(type) %#ok stri = [stri sprintf('\t')]; %#ok else stri = [stri sprintf('%s\t',strtrim(temp))]; %#ok - end; + end otherwise myfailed('Unknown object type when exporting.'); disp(class(temp)) return; - end; - end; - stri = [stri sprintf('\n')]; %#ok - end; + end + end + stri = [stri newline]; %#ok + end if nargout==0 clipboard('copy',stri); mymsgbox('Data copied to clipboard.','Done!'); else varargout{1} = stri; - end; + end else - [filename, pathname] = myuiputfile('*.xls', 'Save as Excel file.'); + [filename, pathname] = myuiputfile('*.xlsx',dprintf('Save as Excel file.')); if isequal(filename,0) || isequal(pathname,0) disp('Aborted'); return; @@ -10597,46 +3555,10 @@ function pin_Motion(type) %#ok myfailed(dprintf('Error:%s',message.message)); return; end - end; -end; + end +end flushlog; -%-------------------------- -function mccheckconsistency %#ok -%-------------------------- -%Check consistency, to prevent earlier -%manual segmentations that have problems with -%direction left/right -global DATA SET NO - - -timeframes=1:SET(NO).TSize; -slice=1:SET(NO).ZSize; - -for timeframe = timeframes - for zloop=slice; - - %Epi - if ~isempty(SET(NO).EpiX) - if not(isnan(SET(NO).EpiX(1,timeframe,zloop))) - - xr = SET(NO).EpiY(:,timeframe,zloop); - yr = SET(NO).EpiX(:,timeframe,zloop); - mx = SET(NO).CenterY; - my = SET(NO).CenterX; - - %Find point closest to cursor - [~,inda] = min(abs(complex(mx-xr,my-yr))); - - SET(NO).EpiX(1:(DATA.NumPoints-inda+1),timeframe,zloop) = yr(inda:end); - SET(NO).EpiY(1:(DATA.NumPoints-inda+1),timeframe,zloop) = xr(inda:end); - SET(NO).EpiX((DATA.NumPoints+1-inda):end,timeframe,zloop) = yr(1:inda); - SET(NO).EpiY((DATA.NumPoints+1-inda):end,timeframe,zloop) = xr(1:inda); - end; - end; - end; -end; - %------------------------------------------ function [x,y,name] = askcontour(queststri) %#ok %------------------------------------------ @@ -10649,7 +3571,7 @@ function pin_Motion(type) %#ok if nargin==0 queststri = 'Choose which contour to import'; -end; +end x = []; y = []; @@ -10667,7 +3589,7 @@ function pin_Motion(type) %#ok if isempty(SET(NO).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; - end; + end y=SET(NO).EndoY; x=SET(NO).EndoX; name='endocardium'; @@ -10676,7 +3598,7 @@ function pin_Motion(type) %#ok if isempty(SET(NO).EpiX) myfailed('No LV epicardium available.',DATA.GUI.Segment); return; - end; + end y=SET(NO).EpiY; x=SET(NO).EpiX; name='epicardium'; @@ -10685,7 +3607,7 @@ function pin_Motion(type) %#ok if isempty(SET(NO).RVEndoX) myfailed('No RV endocardium available.',DATA.GUI.Segment); return; - end; + end y=SET(NO).RVEndoY; x=SET(NO).RVEndoX; name='RVendocardium'; @@ -10694,7 +3616,7 @@ function pin_Motion(type) %#ok if isempty(SET(NO).RVEpiX) myfailed('No RV epicardium available.',DATA.GUI.Segment); return; - end; + end y=SET(NO).RVEpiY; x=SET(NO).RVEpiX; name='RVepicardium'; @@ -10708,7 +3630,7 @@ function pin_Motion(type) %#ok %Function to evaluate matlab commands from compiled version. global DATA SET NO %#ok -eval_str=inputdlg('command:','Execute matlab command'); +eval_str=myinputdlg('command:','Execute matlab command'); if ~isempty(eval_str) try eval(cell2mat(eval_str)); @@ -10720,22 +3642,24 @@ function pin_Motion(type) %#ok segmenthelp('openthislogfile_Callback'); %--------------------------------- -function changewheel_Callback(h,e) %#ok +function changewheel_Callback(h,e) %#ok %--------------------------------- %scrollwheel with modifer. %Tab are not included but you can if you like -global DATA +global SET DATA + if not(DATA.DataLoaded) return; end -if strcmp(DATA.CurrentTheme,'3dp') && any(strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},{'trans3DP','sag3DP','cor3DP'})) +if strcmp(DATA.CurrentTheme,'3dp') && any(strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},{'trans3DP','sag3DP','cor3DP','speedim','viewport'})) segment3dp.tools('scrollwheelfcn3dp',h,e) + return; end -wheelup=e.VerticalScrollCount>0; +wheelup = e.VerticalScrollCount>0; -modifier=char(get(gcbf,'currentmodifier')); +modifier = char(get(gcbf,'currentmodifier')); switch size(modifier,1) case 2 @@ -10748,23 +3672,26 @@ function changewheel_Callback(h,e) %#ok mod_str=modifier; end +%Calculate no +no = DATA.ViewPanels(DATA.CurrentPanel); + switch mod_str - case 'shift' - if wheelup, - previousallframe_Callback; - else - nextallframe_Callback; - end - case 'alt' - if wheelup, - zoomhelper(DATA.Handles.imageaxes(DATA.CurrentPanel),1.2); - else - zoomhelper(DATA.Handles.imageaxes(DATA.CurrentPanel),1/1.2); + case 'shift' + if SET(no).TSize>1 + if wheelup + viewfunctions('switchtimeframe',1); + else + viewfunctions('switchtimeframe',-1); + end end - drawfunctions('viewupdatetextposition'); - drawfunctions('viewupdateannotext'); +% case 'alt' +% if wheelup, +% zoomhelper(DATA.Handles.imageaxes(DATA.CurrentPanel),1.2); +% else +% zoomhelper(DATA.Handles.imageaxes(DATA.CurrentPanel),1/1.2); +% end case 'control' - if wheelup, + if wheelup thumbnailslider_Callback('up'); else thumbnailslider_Callback('down'); @@ -10772,26 +3699,49 @@ function changewheel_Callback(h,e) %#ok case 'shift-alt' case 'control-alt' case 'shift-control' - if wheelup, - contrast_Callback('wheelUpBrightness',DATA.CurrentPanel); + if wheelup + %contrast_Callback('wheelUpBrightness',DATA.CurrentPanel); + SET(no).IntensityMapping.Brightness = SET(no).IntensityMapping.Brightness+0.1; + DATA.ViewIM{DATA.CurrentPanel} = []; + drawfunctions('drawpanel',DATA.CurrentPanel); + drawfunctions('drawthumbnails',1); else - contrast_Callback('wheelDownBrightness',DATA.CurrentPanel); + SET(no).IntensityMapping.Brightness = SET(no).IntensityMapping.Brightness-0.1; + DATA.ViewIM{DATA.CurrentPanel} = []; + drawfunctions('drawpanel',DATA.CurrentPanel); + drawfunctions('drawthumbnails',1); end case 'shift-control-alt' otherwise %no modifier - if e.VerticalScrollCount<0, - if DATA.Synchronize - movealltowardsbase_Callback; - else - movetowardsbase_Callback; - end - else - if DATA.Synchronize - movealltowardsapex_Callback; + if SET(no).ZSize>1 + + if wheelup + viewfunctions('switchslice',1); else - movetowardsapex_Callback; + viewfunctions('switchslice',-1); end - end + + end +end + +%--------------------------------- +function recursekeyreleasefcn(h,fcn) +%--------------------------------- +%Helper function to create callbacks to keyrelease function. +if nargin<2 + fcn = @(x,y)segment('keyreleased',x,y); +end + +allowedtypes = {'figure', 'uicontrol', 'uipushtool', 'uitable', 'uitoolbar'}; + +if any(contains(allowedtypes,h.Type)) + set(h,'KeyReleaseFcn',fcn); +end +if any(contains({'figure','uipanel','uibuttongroup'},h.Type)) + children = get(h,'children'); + for loop=1:length(children) + recursekeyreleasefcn(children(loop),fcn); + end end %--------------------------------- @@ -10800,18 +3750,21 @@ function recursekeypressfcn(h,fcn) %Helper function to create callbacks to keypressed function. if nargin<2 fcn = @(x,y)segment('keypressed',x,y); -end; +end + +allowedtypes = {'figure', 'uicontrol', 'uipushtool', 'uitable', 'uitoolbar'}; %Start with the current handle. -try +if any(contains(allowedtypes,h.Type)) set(h,'keypressfcn',fcn); -catch %#ok -end; +end -children = get(h,'children'); -for loop=1:length(children) - recursekeypressfcn(children(loop),fcn); -end; +if any(contains({'figure','uipanel','uibuttongroup'},h.Type)) + children = get(h,'children'); + for loop=1:length(children) + recursekeypressfcn(children(loop),fcn); + end +end %------------------------------------------ function thumbnailslider_Callback(varargin) @@ -10835,7 +3788,7 @@ function updateslider(whattodo) if isempty(DATA.Handles.thumbnailslider) || (~DATA.DataLoaded) || DATA.Silent DATA.VisibleThumbnails=1:length(SET); return; -end; +end %Get range slidermin=1; @@ -10849,22 +3802,22 @@ function updateslider(whattodo) %No argument simply user changed slider if isempty(DATA.VisibleThumbnails) DATA.VisibleThumbnails=1:min(DATA.Pref.NumberVisibleThumbnails,length(SET)); - end; + end firstthumbnail=slidervalue; lastthumbnail=max(min(firstthumbnail+DATA.Pref.NumberVisibleThumbnails-1,length(SET)),1); else switch whattodo case 'down' - firstthumbnail=max(DATA.VisibleThumbnails(1)-1,1); + firstthumbnail=max(DATA.VisibleThumbnails(1),1); lastthumbnail=min(firstthumbnail+DATA.Pref.NumberVisibleThumbnails-1,length(SET)); slidervalue = firstthumbnail; case 'up' - lastthumbnail=min(DATA.VisibleThumbnails(end)+1,length(SET)); + lastthumbnail=min(DATA.VisibleThumbnails(end),length(SET)); firstthumbnail=max(lastthumbnail-DATA.Pref.NumberVisibleThumbnails+1,1); slidervalue = firstthumbnail; - end; -end; + end +end %Do the update if slidermin==slidermax @@ -10876,7 +3829,7 @@ function updateslider(whattodo) 'enable','off'); else %sliderstep=[1/(length(SET)-DATA.Pref.NumberVisibleThumbnails+1),(slidermax-slidermin+1)];%[0.25/(slidermax-slidermin) 0.5/(slidermax-slidermin)]; - sliderstep = [1/(length(SET)-DATA.Pref.NumberVisibleThumbnails),0.1]; + sliderstep = [1/(length(SET)-DATA.Pref.NumberVisibleThumbnails),2/(length(SET)-DATA.Pref.NumberVisibleThumbnails)]; set(DATA.Handles.thumbnailslider,... 'min',slidermin,... 'max',slidermax,... @@ -10898,13 +3851,13 @@ function updateslider(whattodo) global DATA pathname = getpreferencespath; -GUIPositions = DATA.GUIPositions; %#ok %Saved to file +GUIPositions = DATA.GUIPositions; %Saved to file try save([pathname filesep '.segment_guipositions.mat'],'GUIPositions', DATA.Pref.SaveVersion); catch %#ok myfailed('Could not save GUI positions. Write permission? Disk full?'); return; -end; +end disp('GUI Positions saved.') @@ -10925,23 +3878,24 @@ function updateslider(whattodo) global DATA %GUI positions default values -GUIPositions(1).FileName='segment.fig'; -GUIPositions(1).Position=[0.05 0.05 0.9 0.85];%normalized position +GUIPositions(1).FileName = 'segment.fig'; +GUIPositions(1).Position = [0.05 0.05 0.9 0.85];%normalized position -DATA.GUIPositions=GUIPositions; +DATA.GUIPositions = GUIPositions; -guinames=fieldnames(DATA.GUI); -for loop=1:length(guinames) - gui=getfield(DATA.GUI,guinames{loop}); %#ok +guinames = fieldnames(DATA.GUI); +for loop = 1:length(guinames) + gui = getfield(DATA.GUI,guinames{loop}); %#ok if ~isempty(gui) try setguiposition(gui); + mainresize_Callback; catch me disp(sprintf('Could not reset GUI %s',guinames{loop})); %#ok mydispexception(me); end - end; -end; + end +end %--------------------------------------------------- function corrupted=checkcorrupteddataforautomaticsave(setstruct) %#ok @@ -11047,9 +4001,40 @@ function maxlvdiameter_Callback(type) %drawfunctions('drawmeasures',csax,DATA.CurrentPanel) %DATA.Handles.measureline{DATA.CurrentPanel}{length(SET(csax).Measure)+1} = plot(... % DATA.Handles.imageaxes(DATA.CurrentPanel),[],[],DATA.GUISettings.MeasureLineSpec); - drawfunctions('drawimageview', csax, [1,1],{'one'}) - switchtoslice(SET(csax).Measure(ind).Z(1))%drawfunctions('drawall',1,1) + viewfunctions('setview',1,1,csax,{'one'}); %drawfunctions('drawimageview', csax, [1,1],{'one'}) + %switchtoslice(SET(csax).Measure(ind).Z(1))%drawfunctions('drawall',1,1) + sliceincr = SET(csax).Measure(ind).Z(1) - SET(csax).CurrentSlice; + viewfunctions('switchslice',sliceincr,1); + %----------------------------------------------- +function [intersections, maxintersect] = getendointersection(no) %#ok +%----------------------------------------------- +% Returns the intersection of the endocardial segmentation and the current +% slice and current time frame of SET(no) + +global SET + +intersections = []; +maxintersect = []; + +slice = SET(no).CurrentSlice; +time = SET(no).CurrentTimeFrame; + +if(isfield(SET,'Intersection') && ... + isstruct(SET(no).Intersection)) + + isectnum = strncmp('LV Endocardial',{SET(no).Intersection.Type},14); + + if ~isempty(isectnum) && ... + ~(isempty(SET(no).Intersection(isectnum).Slice(slice).TimeFrame)) + + intersections = SET(no).Intersection(isectnum)... + .Slice(slice).TimeFrame(time).Intersection; + maxintersect = SET(no).Intersection(isectnum).MaxIntersect; + end + +end + %------------------------------------------------------- @@ -11070,13 +4055,6 @@ function maxrvdiameter_Callback(type) csax=findfunctions('findctsaxwithsegmentation','RVEndo'); %Do check if possible to get RV diameter - - - -% if isempty(csax) -% mywarning(dprintf('Unable to get max diameter since no short axis with LV Epi segmentation is available.')) -% return -% end % RV/LV check if isempty(csax)&&isempty(LVsax) @@ -11132,7 +4110,7 @@ function maxrvdiameter_Callback(type) end SET(csax).CurrentTimeFrame = maxtf; - drawfunctions('drawimageview', csax, [1,1],{'one'}) - switchtoslice(SET(csax).Measure(ind).Z(1))%drawfunctions('drawall',1,1) - - \ No newline at end of file + viewfunctions('setview',1,1,csax,{'one'}); %drawfunctions('drawimageview', csax, [1,1],{'one'}) + %switchtoslice(SET(csax).Measure(ind).Z(1))%drawfunctions('drawall',1,1) + sliceincr = SET(csax).Measure(ind).Z(1) - SET(csax).CurrentSlice; + viewfunctions('switchslice',sliceincr,1) \ No newline at end of file diff --git a/source/segment_resources/icon_segment.png b/source/segment_resources/icon_segment.png new file mode 100644 index 0000000..cfd1353 Binary files /dev/null and b/source/segment_resources/icon_segment.png differ diff --git a/source/segmentation.m b/source/segmentation.m index 5a4d231..f89d5ec 100644 --- a/source/segmentation.m +++ b/source/segmentation.m @@ -26,9 +26,29 @@ SET(NO).RVEndoX = SET(NO).EndoX; SET(NO).RVEndoY = SET(NO).EndoY; mymsgbox('LV endo copied to RV endo.','Done!',DATA.GUI.Segment); -drawfunctions('drawallslices'); +drawfunctions('drawno',NO) segment('updatevolume'); + +%---------------------------------------- +function epicopyfromlvendo_Callback %#ok +%---------------------------------------- +%Copy LV Epi from LV Endo in one slice one tf +global SET NO + +tools('enableundo'); +if isempty(SET(NO).EpiX) + SET(NO).EpiX = NaN(size(SET(NO).EndoX)); + SET(NO).EpiY = NaN(size(SET(NO).EndoY)); +end +SET(NO).EpiX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice) = SET(NO).EndoX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); +SET(NO).EpiY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice) = SET(NO).EndoY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); +lv('segmentexpandcontract_Callback',7,'epi'); +disp('LV endo copied to LV epi.'); +drawfunctions('drawno',NO) +segment('updatevolume'); + + %--------------------------------------- function rvcopyfromlvepi_Callback %#ok %--------------------------------------- @@ -43,7 +63,8 @@ SET(NO).RVEpiX = SET(NO).EpiX; SET(NO).RVEpiY = SET(NO).EpiY; mymsgbox('LV epi copied to RV epi.','Done!',DATA.GUI.Segment); -drawfunctions('drawallslices'); + + drawfunctions('drawno',NO) segment('updatevolume'); %--------------------------------- @@ -70,8 +91,6 @@ function clearalllv_Callback(silent) %#ok no = SET(no).Parent; end -removeallpins_Callback(true); %side effect calls enableundo - SET(no).EndoX = []; SET(no).EndoY = []; SET(no).EpiX = []; @@ -84,8 +103,6 @@ function clearalllv_Callback(silent) %#ok SET(no).EpiInterpX = []; SET(no).EpiInterpY = []; -% SET(no).EST = 1; -% SET(no).EDT = 1; %remove Strain tagging analysis if not(isempty(SET(no).StrainTagging)) @@ -151,12 +168,9 @@ function clearalllv_Callback(silent) %#ok end DATA.updatevolumeaxes -segment('updatemodeldisplay'); segment('updatevolume'); if ~silent - segment_main('viewimage_Callback') - drawfunctions('drawimageno'); - drawfunctions('drawallslices'); + drawfunctions('drawno',no) end %----------------------------------------- @@ -202,12 +216,9 @@ function clearallrv_Callback(silent) %#ok DATA.ViewPanelsType{msind}='montage'; end -segment('updatemodeldisplay'); segment('updatevolume'); if ~silent - segment_main('viewimage_Callback') - drawfunctions('drawimageno'); - drawfunctions('drawallslices'); + drawfunctions('drawno',no) end %--------------------------------------- @@ -221,8 +232,6 @@ function clearallrv_Callback(silent) %#ok no = SET(no).Parent; end - -removeallpins_Callback(true); %side effect calls enableundo removeallinterp_Callback(true); SET(no).EndoX = []; SET(no).EndoY = []; @@ -248,7 +257,11 @@ function clearallrv_Callback(silent) %#ok if ~isempty(DATA.GUI.StrainTagging) straintagging.straintagging('close_Callback'); end - runningregistration = SET(no).StrainTagging.runningregistration; + if isfield(SET(no).StrainTagging,'runningregistration') + runningregistration = SET(no).StrainTagging.runningregistration; + else + runningregistration = false; + end if isfield(SET(no).StrainTagging,'transformparameters') transformparameters = SET(no).StrainTagging.transformparameters; end @@ -288,11 +301,8 @@ function clearallrv_Callback(silent) %#ok end DATA.updatevolumeaxes -segment('updatemodeldisplay'); segment('updatevolume'); -segment_main('viewimage_Callback') -drawfunctions('drawimageno'); -drawfunctions('drawallslices'); +drawfunctions('drawno',no) %-------------------------------------------------------- function clearthis_Callback(endo,epi,rvendo,rvepi) %#ok @@ -307,25 +317,25 @@ function clearthis_Callback(endo,epi,rvendo,rvepi) %#ok if nargin<4 rvepi = true; -end; +end if nargin<3 rvendo = true; -end; +end if nargin<2 epi = true; -end; +end if nargin<1 endo = true; -end; +end if DATA.ThisFrameOnly timeframes = SET(no).CurrentTimeFrame; else timeframes = 1:SET(no).TSize; -end; +end ind = true(SET(no).ZSize,1); ind(SET(no).CurrentSlice) = false; clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi); @@ -341,7 +351,7 @@ function clearslices_Callback(endo,epi,rvendo,rvepi) %#ok epi = true; rvendo = true; rvepi = true; -end; +end no = NO; if ~isempty(SET(no).Parent) @@ -354,24 +364,24 @@ function clearslices_Callback(endo,epi,rvendo,rvepi) %#ok if nargin<4 rvepi = true; -end; +end if nargin<3 rvendo = true; -end; +end if nargin<2 epi = true; -end; +end if nargin<1 endo = true; -end; +end if sum(ind)==length(ind) myfailed('No slices selected.',DATA.GUI.Segment); return; -end; +end clearslices(no,ind,1:SET(no).TSize,endo,epi,rvendo,rvepi); @@ -388,19 +398,19 @@ function clearslicesthis_Callback(endo,epi,rvendo,rvepi) %#ok if nargin<4 rvepi = true; -end; +end if nargin<3 rvendo = true; -end; +end if nargin<2 epi = true; -end; +end if nargin<1 endo = true; -end; +end ind = true(SET(no).ZSize,1); ind(SET(no).StartSlice:SET(no).EndSlice)=false; @@ -408,12 +418,12 @@ function clearslicesthis_Callback(endo,epi,rvendo,rvepi) %#ok if sum(ind)==length(ind) myfailed('No slices selected.',DATA.GUI.Segment); return; -end; -if DATA.ThisFrameOnly - tf=SET(no).CurrentTimeFrame; -else - tf=1:SET(no).TSize; end +% if DATA.ThisFrameOnly + tf=SET(no).CurrentTimeFrame; +% else +% tf=1:SET(no).TSize; +% end clearslices(no,ind,tf,endo,epi,rvendo,rvepi); %---------------------------------------------------------------- @@ -424,19 +434,19 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if nargin<7 rvepi = true; -end; +end if nargin<6 rvendo = true; -end; +end if nargin<5 epi = true; -end; +end if nargin<4 endo = true; -end; +end tools('enableundo') @@ -447,25 +457,25 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if endo&&~isempty(SET(no).EndoX) SET(no).EndoX(:,timeframes,zloop) = NaN; SET(no).EndoY(:,timeframes,zloop) = NaN; - end; + end %LV Epi if epi&&~isempty(SET(no).EpiX) SET(no).EpiX(:,timeframes,zloop) = NaN; SET(no).EpiY(:,timeframes,zloop) = NaN; - end; + end %RV Endo if rvendo&&~isempty(SET(no).RVEndoX) SET(no).RVEndoX(:,timeframes,zloop) = NaN; SET(no).RVEndoY(:,timeframes,zloop) = NaN; - end; + end %RV Epi if rvepi&&~isempty(SET(no).RVEpiX) SET(no).RVEpiX(:,timeframes,zloop) = NaN; SET(no).RVEpiY(:,timeframes,zloop) = NaN; - end; + end %Scar if endo&&epi&&~isempty(SET(no).Scar) @@ -475,7 +485,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) SET(no).Scar.NoReflow(:,:,zloop) = false; SET(no).Scar.MyocardMask(:,:,zloop) = false; viability('viabilitycalc'); - end; + end %MaR if endo&&epi&&~isempty(SET(no).MaR) @@ -485,70 +495,42 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) SET(no).MaR.NoReflow(:,:,timeframes,zloop) = false; SET(no).MaR.MyocardMask(:,:,timeframes,zloop) = false; mar('update'); - end; - - %Pins - for tloop=1:length(timeframes) - if endo - if ~isempty(SET(no).EndoPinX) - SET(no).EndoPinX{timeframes(tloop),zloop} = []; - SET(no).EndoPinY{timeframes(tloop),zloop} = []; - end; - end - if rvendo - if ~isempty(SET(no).RVEndoPinX) - SET(no).RVEndoPinX{timeframes(tloop),zloop} = []; - SET(no).RVEndoPinY{timeframes(tloop),zloop} = []; - end; - end; - if epi - if ~isempty(SET(no).EpiPinX) - SET(no).EpiPinX{timeframes(tloop),zloop} = []; - SET(no).EpiPinY{timeframes(tloop),zloop} = []; - end; - end - if rvepi - if ~isempty(SET(no).RVEpiPinX) - SET(no).RVEpiPinX{timeframes(tloop),zloop} = []; - SET(no).RVEpiPinY{timeframes(tloop),zloop} = []; - end; - end; - end; + end %Interp Points for tloop=1:length(timeframes) if endo if ~isempty(SET(no).EndoInterpX) SET(no).EndoInterpX{timeframes(tloop),zloop} = []; SET(no).EndoInterpY{timeframes(tloop),zloop} = []; - end; + end end if rvendo if ~isempty(SET(no).RVEndoInterpX) SET(no).RVEndoInterpX{timeframes(tloop),zloop} = []; SET(no).RVEndoInterpY{timeframes(tloop),zloop} = []; - end; - end; + end + end if epi if ~isempty(SET(no).EpiInterpX) SET(no).EpiInterpX{timeframes(tloop),zloop} = []; SET(no).EpiInterpY{timeframes(tloop),zloop} = []; - end; + end end if rvepi if ~isempty(SET(no).RVEpiInterpX) SET(no).RVEpiInterpX{timeframes(tloop),zloop} = []; SET(no).RVEpiInterpY{timeframes(tloop),zloop} = []; - end; - end; - end; + end + end + end if endo SET(no).EndoDraged(timeframes,zloop) = false; - end; + end if epi SET(no).EpiDraged(timeframes,zloop) = false; - end; - end; -end; + end + end +end %remove Strain tagging analysis if not(isempty(SET(no).StrainTagging)) @@ -595,10 +577,10 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) end %safety check so we dont go out of bounds when doing the montage LV -ind=find(findfunctions('findslicewithendo',no)+... - findfunctions('findslicewithepi',no)+... - findfunctions('findslicewithrvendo',no)+... - findfunctions('findslicewithrvepi',no)); +ind=find(findfunctions('findslicewithendo',no,timeframes)+... + findfunctions('findslicewithepi',no,timeframes)+... + findfunctions('findslicewithrvendo',no,timeframes)+... + findfunctions('findslicewithrvepi',no,timeframes)); msind = find(strcmp({DATA.ViewPanelsType{DATA.ViewPanels==no}},'montagesegmented')); if ~isempty(msind) && isempty(ind) @@ -607,10 +589,8 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) DATA.updatevolumeaxes segment('updatevolume'); -segment('updatemodeldisplay'); -segment('makeviewim',DATA.CurrentPanel) -drawfunctions('drawimageno'); -drawfunctions('drawallslices'); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawno',no) %--------------------------- function clear_helper %#ok @@ -628,7 +608,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) timeframes=SET(no).CurrentTimeFrame; else timeframes=1:SET(no).TSize; -end; +end ind = true(SET(no).ZSize,1); ind(SET(no).StartSlice:SET(no).EndSlice)=false; clearslices(no,ind,timeframes); @@ -666,7 +646,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) pos = calcfunctions('rlapfh2xyz',destno,pos(:,1),pos(:,2),pos(:,3)); destx(:,tloop) = pos(1,:)'; desty(:,tloop) =pos(2,:)'; - end; + end desttimeframes = 1:size(x,2); %--- end of timeresolved (interpolation) else @@ -681,15 +661,15 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) [~,nt] = min(abs(desttime-sourcetime(tloop))); %find best matching timeframe in destination if isnan(nt) nt = 1; - end; + end [pos] = calcfunctions('xyz2rlapfh',sourceno,sourcex(:,tloop),sourcey(:,tloop),repmat(sourceslice,size(sourcex,1),1)); pos = calcfunctions('rlapfh2xyz',destno,pos(:,1),pos(:,2),pos(:,3)); destx(:,tloop) = pos(1,:)'; desty(:,tloop) =pos(2,:)'; desttimeframes(tloop) = nt; - end; %source frame contains segmentation - end; %loop over souce timeframes + end %source frame contains segmentation + end %loop over souce timeframes ind = find(desttimeframes~=0); desttimeframes = desttimeframes(ind); @@ -697,11 +677,11 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if ~isempty(ind) destx = destx(:,ind); desty = desty(:,ind); - end; + end - end; + end %--- End not time resolved -end; +end %---------------------------------------------------------------------------------- @@ -739,7 +719,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) for tloop = 1:length(desttime) [~,ind] = min(abs(SET(tono).TimeVector-desttime(tloop))); desttimeframes(tloop) = ind; -end; +end %Loop over the number of slices in destination images for zloop=1:SET(tono).ZSize @@ -756,16 +736,16 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) [tempx,tempy,desttimeframes(destloop)] = importcoordinatehelper(tono,desttime(destloop),fromno,SET(fromno).EndoX(:,:,sourceslice),SET(fromno).EndoY(:,:,sourceslice),importtf,sourceslice); SET(tono).EndoX(:,destloop,destslice) = tempx; SET(tono).EndoY(:,destloop,destslice) = tempy; - end; + end end else [tempx,tempy,desttimeframes] = importcoordinatehelper(tono,desttime,fromno,SET(fromno).EndoX(:,:,sourceslice),SET(fromno).EndoY(:,:,sourceslice),sourcetime,sourceslice); if ~isempty(desttimeframes) SET(tono).EndoX(:,desttimeframes,destslice) = tempx; SET(tono).EndoY(:,desttimeframes,destslice) = tempy; - end; + end end - end; + end %Epi if doepi @@ -775,16 +755,16 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) [tempx,tempy,desttimeframes(destloop)] = importcoordinatehelper(tono,desttime(destloop),fromno,SET(fromno).EpiX(:,:,sourceslice),SET(fromno).EpiY(:,:,sourceslice),importtf,sourceslice); SET(tono).EpiX(:,destloop,destslice) = tempx; SET(tono).EpiY(:,destloop,destslice) = tempy; - end; + end end else [tempx,tempy,desttimeframes] = importcoordinatehelper(tono,desttime,fromno,SET(fromno).EpiX(:,:,sourceslice),SET(fromno).EpiY(:,:,sourceslice),sourcetime,sourceslice); if ~isempty(desttimeframes) SET(tono).EpiX(:,desttimeframes,destslice) = tempx; SET(tono).EpiY(:,desttimeframes,destslice) = tempy; - end; + end end - end; + end %RVEndo if dorvendo @@ -792,8 +772,8 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if ~isempty(desttimeframes) SET(tono).RVEndoX(:,desttimeframes,destslice) = tempx; SET(tono).RVEndoY(:,desttimeframes,destslice) = tempy; - end; - end; + end + end %RVEpi if dorvepi @@ -801,10 +781,10 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if ~isempty(desttimeframes) SET(tono).RVEpiX(:,desttimeframes,destslice) = tempx; SET(tono).RVEpiY(:,desttimeframes,destslice) = tempy; - end; - end; + end + end -end; +end %-------------------------------------------------------------------------- function [sourceslice,destslice,sourcetime,desttime,zdirsource,zdirdest] = findmatchingslices ... @@ -829,7 +809,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) anglediff = acos(zdirsource*(zdirdest'))*180/pi; -if anglediff>10 && any([doendo,doepi,dorvendo,dorvepi]); +if anglediff>10 && any([doendo,doepi,dorvendo,dorvepi]) myfailed('Angle difference between the two image stacks is greater than 10 degrees.',DATA.GUI.Segment); sourceslice = []; destslice = []; @@ -839,7 +819,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) zdirdest = []; %Later offer to do anyway return; -end; +end %Set up structure on positions for source slices in the ind = (0:(SET(fromno).ZSize-1))'; @@ -885,12 +865,12 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) else matches(loop) = minind(1); end -end; +end temp = unique(matches); -if length(temp)1) @@ -911,7 +891,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) indt = max(indt,1); desttime = 1; - s = inputdlg({'Enter timeframe'},'TimeFrame',1,{sprintf('%d',indt)}); + s = myinputdlg({'Enter timeframe'},'TimeFrame',1,{sprintf('%d',indt)}); close(16); if isempty(s) myfailed('Invalid timeframe.',DATA.GUI.Segment); @@ -921,12 +901,12 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if not(ok) myfailed('Invalid timeframe.',DATA.GUI.Segment); return; - end; + end if (sourcetime<1)||(sourcetime>length(SET(fromno).LVV)) myfailed(dprintf('Needs to be [1..%d',length(SET(fromno).LVV)),DATA.GUI.Segment); return; - end; - end; + end + end end else if SET(tono).TSize==1 && SET(fromno).TSize==1 @@ -936,33 +916,33 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) desttime = SET(tono).TimeVector; sourcetime = SET(fromno).TimeVector; end -end; +end %Ensure that destination data exists if doendo if isempty(SET(tono).EndoX) SET(tono).EndoX = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); SET(tono).EndoY = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); - end; -end; + end +end if doepi if isempty(SET(tono).EpiX) SET(tono).EpiX = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); SET(tono).EpiY = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); - end; -end; + end +end if dorvendo if isempty(SET(tono).RVEndoX) SET(tono).RVEndoX = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); SET(tono).RVEndoY = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); - end; -end; + end +end if dorvepi if isempty(SET(tono).RVEpiX) SET(tono).RVEpiX = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); SET(tono).RVEpiY = nan([DATA.NumPoints SET(tono).TSize SET(tono).ZSize]); - end; -end; + end +end %Loop over the number of slices in destination images sourceslice = nan(SET(tono).ZSize,1); @@ -992,7 +972,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if isempty(SET(cineshortaxisno).EndoX) || isempty(SET(cineshortaxisno).EpiX) myfailed('No LV segmentation available.'); return; -end; +end %Check what timeframe to take from importtf = round(2/3*SET(cineshortaxisno).TSize); %approximately diastasis @@ -1000,12 +980,12 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) %If no in diastasis, then try ESV (tested this seems better than EDT) if isnan(SET(cineshortaxisno).LVV(importtf)) importtf = SET(cineshortaxisno).EST; -end; +end %If no in EST try EDT if isnan(SET(cineshortaxisno).LVV(importtf)) importtf = SET(cineshortaxisno).EDT; -end; +end importsegmentationwithsnap_Callback(cineshortaxisno,importtf,[1,1,0,0]); @@ -1031,7 +1011,7 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) if isempty(SET(cineshortaxisno).EndoX) || isempty(SET(cineshortaxisno).EpiX) myfailed('No LV segmentation available.'); return; -end; +end %Check what timeframe to take from importtf = round(2/3*SET(cineshortaxisno).TSize); %approximately diastasis @@ -1039,12 +1019,12 @@ function clearslices(no,ind,timeframes,endo,epi,rvendo,rvepi) %If no in diastasis, then try ESV (tested this seems better than EDT) if isnan(SET(cineshortaxisno).LVV(importtf)) importtf = SET(cineshortaxisno).EST; -end; +end %If no in EST try EDT if isnan(SET(cineshortaxisno).LVV(importtf)) importtf = SET(cineshortaxisno).EDT; -end; +end %import contour txmapimport = true; @@ -1068,16 +1048,19 @@ function importsegmentationwithsnap_Callback(no,importtf,doseg,txmapimport) [destno,sourceno] = importsegmentation_Callback(no,importtf,doseg); case 4 [destno,sourceno] = importsegmentation_Callback(no,importtf,doseg,txmapimport); -end; +end + +if destno==0 && sourceno==0 %Added condition, to prevent bug when importsegmentation is cancelled by clicking 'Cancel' button + return; +end %Adjust to contours if ~isequal(SET(destno).AcquisitionTime,SET(sourceno).AcquisitionTime) importadjust(NO); -end; +end -segment('updatemodeldisplay'); lvsegchanged = true; segment('updatevolume',lvsegchanged); -drawfunctions('drawallslices'); +drawfunctions('drawno',NO) %--------------------------------------------------------------------------- function [destno,sourceno] = importsegmentation_Callback(no,importtf,doseg,txmapimport) @@ -1097,7 +1080,7 @@ function importsegmentationwithsnap_Callback(no,importtf,doseg,txmapimport) if length(SET)<2 myfailed('Only one image stack in memory, import from file instead (under File menu).',DATA.GUI.Segment); return; -end; +end if nargin==0 %Find what imagestack @@ -1110,20 +1093,22 @@ function importsegmentationwithsnap_Callback(no,importtf,doseg,txmapimport) s = mymenu('Select which stack to import from',menuitems,DATA.GUI.Segment); if s == 0 %operation cancelled + sourceno=0; + destno=0; return; else no = impstacks(s); - end; -end; + end +end if no==NO myfailed('Cannot import from same image stack.',DATA.GUI.Segment); return; -end; +end if (no>length(SET))||(no<1) myfailed('Invalid image stack selected.',DATA.GUI.Segment); return; -end; +end sourceno = no; destno = NO; @@ -1134,22 +1119,22 @@ function importsegmentationwithsnap_Callback(no,importtf,doseg,txmapimport) doendo = true; else doendo = false; -end; +end if ~isempty(SET(sourceno).EpiX) && ~all(isnan(SET(sourceno).EpiX(:))) doepi = true; else doepi = false; -end; +end if ~isempty(SET(sourceno).RVEndoX)&& ~all(isnan(SET(sourceno).RVEndoX(:))) dorvendo = true; else dorvendo = false; -end; +end if ~isempty(SET(sourceno).RVEpiX)&& ~all(isnan(SET(sourceno).RVEpiX(:))) dorvepi = true; else dorvepi = false; -end; +end else %assure it is a logical; doseg=logical(doseg); @@ -1163,12 +1148,13 @@ function importsegmentationwithsnap_Callback(no,importtf,doseg,txmapimport) myfailed('No segmentation in image to import from.',DATA.GUI.Segment); return; end - +tools('connectinterpolation',no,{'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}); if nargin > 1 importsegmentationhelper(destno,sourceno,doendo,doepi,dorvendo,dorvepi,importtf,txmapimport); else importsegmentationhelper(destno,sourceno,doendo,doepi,dorvendo,dorvepi); end +viewfunctions('setview') %----------------------------- function e = edgehelper(im) @@ -1201,7 +1187,7 @@ function importadjust(no) if nargin<1 no = NO; -end; +end tools('enableundo'); @@ -1210,11 +1196,11 @@ function importadjust(no) %Check if there is segmentation if isempty(SET(no).EndoX) && isempty(SET(no).EpiX) return; -end; +end %Loop over slices otable = zeros(m*2+1,m*2+1,SET(no).ZSize); -h = waitbar(0,dprintf('Please wait registering contours.')); +h = mywaitbarstart(SET(no).ZSize,dprintf('Please wait registering contours.')); for z = 1:SET(no).ZSize %Loop over timeframes and update otable @@ -1223,10 +1209,10 @@ function importadjust(no) doimage = false; if ~isempty(SET(no).EndoX) && ~isnan(SET(no).EndoX(1,t,z)) doimage = true; - end; + end if ~isempty(SET(no).EpiX) && ~isnan(SET(no).EpiX(1,t,z)) doimage = true; - end; + end if doimage %Extract image @@ -1243,21 +1229,21 @@ function importadjust(no) endox = SET(no).EndoX(:,t,z); endoy = SET(no).EndoY(:,t,z); otable(dx+m+1,dy+m+1,z) = otable(dx+m+1,dy+m+1,z)+score(edgeim,endoy+dy,endox+dx); - end; + end if ~isempty(SET(no).EpiX) && ~isnan(SET(no).EpiX(1,t,z)) epix = SET(no).EpiX(:,t,z); epiy = SET(no).EpiY(:,t,z); otable(dx+m+1,dy+m+1,z) = otable(dx+m+1,dy+m+1,z)+score(edgeim,epiy+dy,epix+dx); - end; + end - end; %dy - end; %dx - end; %doimage - end; %t + end %dy + end %dx + end %doimage + end %t - waitbar(z/SET(no).ZSize,h); -end; %Z + h = mywaitbarupdate(h); +end %Z %Loop over slices again for z = 1:SET(no).ZSize @@ -1271,9 +1257,9 @@ function importadjust(no) ox = dx; oy = dy; maxvalue = otable(dx+m+1,dy+m+1,z); - end; - end; - end; + end + end + end %[ox oy] @@ -1282,9 +1268,9 @@ function importadjust(no) SET(no).EndoY(:,:,z) = SET(no).EndoY(:,:,z)+oy; SET(no).EpiX(:,:,z) = SET(no).EpiX(:,:,z)+ox; SET(no).EpiY(:,:,z) = SET(no).EpiY(:,:,z)+oy; -end; %Z +end %Z -close(h); +mywaitbarclose(h); % figure(29); % slice = SET(no).CurrentSlice; @@ -1313,203 +1299,18 @@ function importadjust(no) if nargin<1 no = NO; -end; +end importadjust(no); -segment('updatemodeldisplay'); segment('updatevolume'); -drawfunctions('updatenopanels',no); - +drawfunctions('drawno',no) %---------------------- function z = score(im,x,y) %---------------------- %score for endo segmentation z = sum(interp2(im,x,y,'linear')); -%-------------------------------------- -function removepin_Callback(type,m) %#ok -%-------------------------------------- -%Removes pins -global SET NO - -tools('enableundo'); -if nargin~=1 - mydisp('Remove pin by right mouse click on the pin.'); -end; - -[x,y,slice] = segment('getclickedcoords'); - -%Find what pin. -switch type - case 'endo' - if isempty(SET(NO).EndoPinX) - return; - end; - xm = SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice}; - case 'epi' - if isempty(SET(NO).EpiPinX) - return; - end; - xm = SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice}; - case 'rvendo' - if isempty(SET(NO).RVEndoPinX) - return; - end; - xm = SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice}; - ym = SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice}; -end; - -%Calculate distance -[~,tempind] = min(sqrt((xm-y).^2+(ym-x).^2)); - -%remove from endo and put back -ind = true(length(xm),1); -ind(tempind)=false; - -switch type - case 'endo' - SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice} = xm(ind); - SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice} = ym(ind); - case 'epi' - SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice} = xm(ind); - SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice} = ym(ind); - case 'rvendo' - SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice} = xm(ind); - SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice} = ym(ind); -end; - -segment('updatemodeldisplay'); -drawfunctions('drawsliceno'); - -%-------------------------------------- -function removethispins_Callback(endo,epi,rvendo,rvepi) %#ok -%-------------------------------------- -%Remove pins in this slice and timeframe -global SET NO - - -if nargin<4 - endo=true; - epi=true; - rvendo=true; - rvepi=true; -end - -tools('enableundo'); -[~,~,slice] = segment('getclickedcoords'); - -if endo && ~isempty(SET(NO).EndoPinX) - SET(NO).EndoPinX{SET(NO).CurrentTimeFrame,slice} = []; - SET(NO).EndoPinY{SET(NO).CurrentTimeFrame,slice} = []; -end; - -if epi && ~isempty(SET(NO).EpiPinX) - SET(NO).EpiPinX{SET(NO).CurrentTimeFrame,slice} = []; - SET(NO).EpiPinY{SET(NO).CurrentTimeFrame,slice} = []; -end; - -if rvendo && ~isempty(SET(NO).RVEndoPinX) - SET(NO).RVEndoPinX{SET(NO).CurrentTimeFrame,slice} = []; - SET(NO).RVEndoPinY{SET(NO).CurrentTimeFrame,slice} = []; -end; - -if rvepi && ~isempty(SET(NO).RVEpiPinX) - SET(NO).RVEpiPinX{SET(NO).CurrentTimeFrame,slice} = []; - SET(NO).RVEpiPinY{SET(NO).CurrentTimeFrame,slice} = []; -end; - -segment('updatemodeldisplay'); -drawfunctions('drawsliceno'); - -%----------------------------------------- -function removeallpins_Callback(silent,endo,epi,rvendo,rvepi) -%----------------------------------------- -%Remove all pins -global SET NO - -if nargin == 0 - silent=false; -end - -if nargin<5 - endo=true; - epi=true; - rvendo=true; - rvepi=true; -end - -tools('enableundo'); - -if endo && ~isempty(SET(NO).EndoPinX) - SET(NO).EndoPinX = []; - SET(NO).EndoPinY = []; -end -if epi && ~isempty(SET(NO).EpiPinX) - SET(NO).EpiPinX = []; - SET(NO).EpiPinY = []; -end - -if rvendo && ~isempty(SET(NO).RVEndoPinX) - SET(NO).RVEndoPinX = []; - SET(NO).RVEndoPinY = []; -end; -if rvepi && ~isempty(SET(NO).RVEpiPinX) - SET(NO).RVEpiPinX = []; - SET(NO).RVEpiPinY = []; -end; - -if not(silent) - segment('updatemodeldisplay'); - drawfunctions('drawallslices'); -end; - -%--------------------------------------------------- -function removeallpinsthisslice_Callback(current,endo,epi,rvendo,rvepi) %#ok -%--------------------------------------------------- -%Remove all pins in this slice -global SET NO - -tools('enableundo'); - -if (nargin>0) && (current) - slice = SET(NO).CurrentSlice; -else - % never happens, or?? /JU - [~,~,slice] = segment('getclickedcoords'); -end; - -if nargin<5 - endo=true; - epi=true; - rvendo=true; - rvepi=true; -end - -for tloop=1:SET(NO).TSize - if endo && ~isempty(SET(NO).EndoPinX) - SET(NO).EndoPinX{tloop,slice} = []; - SET(NO).EndoPinY{tloop,slice} = []; - end; - if epi && ~isempty(SET(NO).EpiPinX) - SET(NO).EpiPinX{tloop,slice} = []; - SET(NO).EpiPinY{tloop,slice} = []; - end; - if rvendo && ~isempty(SET(NO).RVEndoPinX) - SET(NO).RVEndoPinX{tloop,slice} = []; - SET(NO).RVEndoPinY{tloop,slice} = []; - end; - if rvepi && ~isempty(SET(NO).RVEpiPinX) - SET(NO).RVEpiPinX{tloop,slice} = []; - SET(NO).RVEpiPinY{tloop,slice} = []; - end; -end; - -segment('updatemodeldisplay'); -drawfunctions('drawsliceno'); - %------------------------------------------------------ function removeallinterp_Callback(silent,no,arg,indarg) %------------------------------------------------------ @@ -1596,50 +1397,47 @@ function removeallinterp_Callback(silent,no,arg,indarg) if arg.rvendo && ~isempty(SET(no).RVEndoInterpX) SET(no).RVEndoInterpX(indarg.rvendoind,:) = cell(1,1); SET(no).RVEndoInterpY(indarg.rvendoind,:) = cell(1,1); -end; +end if arg.rvepi && ~isempty(SET(no).RVEpiInterpX) SET(no).RVEpiInterpX(indarg.rvepiind,:) = cell(1,1); SET(no).RVEpiInterpY(indarg.rvepiind,:) = cell(1,1); -end; +end if not(silent) - segment('updatemodeldisplay'); - drawfunctions('drawallslices'); -end; + drawfunctions('drawno',no) +end %------------------------------------------------- -function interpolatedelineationovertime_Callback +function interpolatedelineationovertime_Callback %#ok icon callback %------------------------------------------------- % Interpolate LV or RV delineation over time from existing delineations global SET NO DATA no = NO; - - -segtodo=mymenu('Select delineation to interpolate', 'LV endocardium', 'LV epicardium', 'RV endocardium', 'RV epicardium'); +segtodo = mymenu('Select delineation to interpolate', 'LV endocardium', 'LV epicardium', 'RV endocardium', 'RV epicardium'); if isequal(segtodo,0) - myfailed('Aborted.'); return; -end; - +end +interptypes = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; +tools('connectinterpolation',no,interptypes(segtodo)); switch segtodo - case 1 %LV endocardium - X=SET(no).EndoX; - Y=SET(no).EndoY; - str='No LV endocardium to interpolate.'; + case 1 %LV endocardium + X = SET(no).EndoX; + Y = SET(no).EndoY; + str = 'No LV endocardium to interpolate.'; case 2 %LV epicardium - X=SET(no).EpiX; - Y=SET(no).EpiY; + X = SET(no).EpiX; + Y = SET(no).EpiY; str = 'No LV epicardium to interpolate.'; case 3 %RV endocardium - X=SET(no).RVEndoX; - Y=SET(no).RVEndoY; - str= 'No RV endocardium to interpolate.'; + X = SET(no).RVEndoX; + Y = SET(no).RVEndoY; + str = 'No RV endocardium to interpolate.'; case 4 %RV epicardium - X=SET(no).RVEpiX; - Y=SET(no).RVEpiY; + X = SET(no).RVEpiX; + Y = SET(no).RVEpiY; str = 'No RV epicardium to interpolate.'; end @@ -1648,13 +1446,13 @@ function removeallinterp_Callback(silent,no,arg,indarg) return; end -interpolationtype=mymenu('Linear or sinusoidal interpolation?', 'Sinusoidal', 'Linear') +interpolationtype = mymenu('Linear or sinusoidal interpolation?', 'Sinusoidal', 'Linear'); -selectedslices=SET(no).StartSlice:SET(no).EndSlice; +selectedslices = SET(no).StartSlice:SET(no).EndSlice; hasseg = squeeze(~isnan(X(1,:,:)));%squeeze(~isnan(X(1,:,selectedslices))); % hasseg(tf, sl) if isrow(hasseg) - hasseg=hasseg'; + hasseg = hasseg'; end %tf_hasseg = sum(hasseg,2) > 0; % timeframes with segmentation @@ -1666,223 +1464,137 @@ function removeallinterp_Callback(silent,no,arg,indarg) %New scheme does only for selected slices % Perform interpolation for all slices for sloop = selectedslices%1:Nsl -tf_hasseg=hasseg(:,sloop); - for tloop = 1:Ntf - % no interpolation needed if we already have one - if tf_hasseg(tloop);%tf_hasseg(tloop) - continue - end - % Find lower and upper timeframes for interpolation - tf_hasseg_ind = find(tf_hasseg)'; - tf_hasseg_ind_periodic = [tf_hasseg_ind-Ntf tf_hasseg_ind tf_hasseg_ind+Ntf]; - tf_hasseg_ind_periodic_wrap = [tf_hasseg_ind tf_hasseg_ind tf_hasseg_ind]; + tf_hasseg = hasseg(:,sloop); + if any(tf_hasseg) + for tloop = 1:Ntf + % no interpolation needed if we already have one + if tf_hasseg(tloop) %tf_hasseg(tloop) + continue + end + % Find lower and upper timeframes for interpolation + tf_hasseg_ind = find(tf_hasseg)'; + tf_hasseg_ind_periodic = [tf_hasseg_ind-Ntf tf_hasseg_ind tf_hasseg_ind+Ntf]; + tf_hasseg_ind_periodic_wrap = [tf_hasseg_ind tf_hasseg_ind tf_hasseg_ind]; - lowerindpos = find(tf_hasseg_ind_periodic < tloop, 1, 'last'); - upperindpos = find(tf_hasseg_ind_periodic > tloop, 1, 'first'); + lowerindpos = find(tf_hasseg_ind_periodic < tloop, 1, 'last'); + upperindpos = find(tf_hasseg_ind_periodic > tloop, 1, 'first'); - lowerind = tf_hasseg_ind_periodic_wrap(lowerindpos); - upperind = tf_hasseg_ind_periodic_wrap(upperindpos); + lowerind = tf_hasseg_ind_periodic_wrap(lowerindpos); + upperind = tf_hasseg_ind_periodic_wrap(upperindpos); - % Interpolation weight - - iw = (tloop-tf_hasseg_ind_periodic(lowerindpos))/(tf_hasseg_ind_periodic(upperindpos)-tf_hasseg_ind_periodic(lowerindpos)); - if interpolationtype==1 %if sinusoidal interpolation is chosen - iw = 0.5*(1-cos(pi*iw)); - end -% -% New scheme does only for selected slices % Perform interpolation for all slices -% for sloop = selectedslices%1:Nsl - % Convert segmentations to polar coordinates (R,Theta) - lowerX = X(1:end-1,lowerind,sloop); - lowerY = Y(1:end-1,lowerind,sloop); - lower_mx = mean(lowerX); - lower_my = mean(lowerY); - lowerR = sqrt((lowerX - lower_mx).^2 + (lowerY - lower_my).^2); - lowerT = atan2(lowerY-lower_my, lowerX-lower_mx); - - [~,I] = sort(lowerT); - lowerRsort = lowerR(I); - lowerTsort = lowerT(I); - - upperX = X(1:end-1,upperind,sloop); - upperY = Y(1:end-1,upperind,sloop); - upper_mx = mean(upperX); - upper_my = mean(upperY); - upperR = sqrt((upperX - upper_mx).^2 + (upperY - upper_my).^2); - upperT = atan2(upperY-upper_my, upperX-upper_mx); - - [~,I] = sort(upperT); - upperRsort = upperR(I); - upperTsort = upperT(I); - - % Skip slices where we don't have stuff to interpolate from - if any(isnan([lowerR' upperR' lowerT' upperT'])) - continue + % Interpolation weight + + iw = (tloop-tf_hasseg_ind_periodic(lowerindpos))/(tf_hasseg_ind_periodic(upperindpos)-tf_hasseg_ind_periodic(lowerindpos)); + if interpolationtype==1 %if sinusoidal interpolation is chosen + iw = 0.5*(1-cos(pi*iw)); end - - % Interpolate to normalized Theta range - Npts = size(X, 1); - Tnorm = linspace(-pi,pi, Npts); - Tnorm = Tnorm(1:end-1); - - lowerRint = interp1([lowerTsort-2*pi; lowerTsort; lowerTsort+2*pi], ... - [lowerRsort; lowerRsort; lowerRsort], Tnorm, 'linear'); - upperRint = interp1([upperTsort-2*pi; upperTsort; upperTsort+2*pi], ... - [upperRsort; upperRsort; upperRsort], Tnorm, 'linear'); - - % Perform interpolation - midR = (1-iw)*lowerRint + iw*upperRint; - mid_mx = (1-iw)*lower_mx + iw*upper_mx; - mid_my = (1-iw)*lower_my + iw*upper_my; - - % Go back to cartesian - segoutX = mid_mx + midR.*cos(Tnorm); - segoutY = mid_my + midR.*sin(Tnorm); - - % A little smoothing - segoutX = conv([segoutX segoutX segoutX], [1 1 1]/3, 'same'); - segoutX = segoutX(Npts:(2*Npts-1)); - - segoutY = conv([segoutY segoutY segoutY], [1 1 1]/3, 'same'); - segoutY = segoutY(Npts:(2*Npts-1)); - - % Store as periodic - segoutX(Npts) = segoutX(1); - segoutY(Npts) = segoutY(1); - - % Store - - switch segtodo - case 1 %LV endocardium - SET(no).EndoX(:,tloop,sloop) = segoutX; - SET(no).EndoY(:,tloop,sloop) = segoutY; - case 2 %LV epicardium - SET(no).EpiX(:,tloop,sloop) = segoutX; - SET(no).EpiY(:,tloop,sloop) = segoutY; - case 3 %RV endocardium - SET(no).RVEndoX(:,tloop,sloop) = segoutX; - SET(no).RVEndoY(:,tloop,sloop) = segoutY; - case 4 %RV epicardium - SET(no).RVEpiX(:,tloop,sloop) = segoutX; - SET(no).RVEpiY(:,tloop,sloop) = segoutY; + % + % New scheme does only for selected slices % Perform interpolation for all slices + % for sloop = selectedslices%1:Nsl + % Convert segmentations to polar coordinates (R,Theta) + lowerX = X(1:end-1,lowerind,sloop); + lowerY = Y(1:end-1,lowerind,sloop); + lower_mx = mean(lowerX); + lower_my = mean(lowerY); + lowerR = sqrt((lowerX - lower_mx).^2 + (lowerY - lower_my).^2); + lowerT = atan2(lowerY-lower_my, lowerX-lower_mx); + + [~,I] = sort(lowerT); + lowerRsort = lowerR(I); + lowerTsort = lowerT(I); + + upperX = X(1:end-1,upperind,sloop); + upperY = Y(1:end-1,upperind,sloop); + upper_mx = mean(upperX); + upper_my = mean(upperY); + upperR = sqrt((upperX - upper_mx).^2 + (upperY - upper_my).^2); + upperT = atan2(upperY-upper_my, upperX-upper_mx); + + [~,I] = sort(upperT); + upperRsort = upperR(I); + upperTsort = upperT(I); + + % Skip slices where we don't have stuff to interpolate from + if any(isnan([lowerR' upperR' lowerT' upperT'])) + continue + end + + % Interpolate to normalized Theta range + Npts = size(X, 1); + Tnorm = linspace(-pi,pi, Npts); + Tnorm = Tnorm(1:end-1); + + x = [lowerTsort-2*pi; lowerTsort; lowerTsort+2*pi]; + y = [lowerRsort; lowerRsort; lowerRsort]; + len = sqrt(... + conv2(x',[1 -1],'valid').^2+... + conv2(y',[1 -1],'valid').^2); + len = [0;len(:)]; %Add zero first + len = cumsum(len); + tempind = find(conv2(len,[1;-1],'valid')~=0); %Remove doublets + % len = [len(1);len(tempind+1)]; %used in interpolation later + x = [x(1); x(tempind+1)]; + y = [y(1); y(tempind+1)]; + % totallength = len(end);%used in interpolation later + + lowerRint = interp1(x,y, Tnorm, 'linear'); + + x = [upperTsort-2*pi; upperTsort; upperTsort+2*pi]; + y = [upperRsort; upperRsort; upperRsort]; + len = sqrt(... + conv2(x',[1 -1],'valid').^2+... + conv2(y',[1 -1],'valid').^2); + len = [0;len(:)]; %Add zero first + len = cumsum(len); + tempind = find(conv2(len,[1;-1],'valid')~=0); %Remove doublets + % len = [len(1);len(tempind+1)]; %used in interpolation later + x = [x(1); x(tempind+1)]; + y = [y(1); y(tempind+1)]; + + + upperRint = interp1(x, y, Tnorm, 'linear'); + + % Perform interpolation + midR = (1-iw)*lowerRint + iw*upperRint; + mid_mx = (1-iw)*lower_mx + iw*upper_mx; + mid_my = (1-iw)*lower_my + iw*upper_my; + + % Go back to cartesian + segoutX = mid_mx + midR.*cos(Tnorm); + segoutY = mid_my + midR.*sin(Tnorm); + + % A little smoothing + segoutX = conv([segoutX segoutX segoutX], [1 1 1]/3, 'same'); + segoutX = segoutX(Npts:(2*Npts-1)); + + segoutY = conv([segoutY segoutY segoutY], [1 1 1]/3, 'same'); + segoutY = segoutY(Npts:(2*Npts-1)); + + % Store as periodic + segoutX(Npts) = segoutX(1); + segoutY(Npts) = segoutY(1); + + % Store + switch segtodo + case 1 %LV endocardium + SET(no).EndoX(:,tloop,sloop) = segoutX; + SET(no).EndoY(:,tloop,sloop) = segoutY; + case 2 %LV epicardium + SET(no).EpiX(:,tloop,sloop) = segoutX; + SET(no).EpiY(:,tloop,sloop) = segoutY; + case 3 %RV endocardium + SET(no).RVEndoX(:,tloop,sloop) = segoutX; + SET(no).RVEndoY(:,tloop,sloop) = segoutY; + case 4 %RV epicardium + SET(no).RVEpiX(:,tloop,sloop) = segoutX; + SET(no).RVEpiY(:,tloop,sloop) = segoutY; + end end - - end end - - -% for sloop = selectedslices%1:Nsl -% for tloop = 1:Ntf -% % no interpolation needed if we already have one -% if hasseg(tloop,sloop-SET(no).StartSlice+1);%tf_hasseg(tloop) -% continue -% end -% -% % Find lower and upper timeframes for interpolation -% tf_hasseg_ind = find(tf_hasseg)'; -% tf_hasseg_ind_periodic = [tf_hasseg_ind-Ntf tf_hasseg_ind tf_hasseg_ind+Ntf]; -% tf_hasseg_ind_periodic_wrap = [tf_hasseg_ind tf_hasseg_ind tf_hasseg_ind]; -% -% lowerindpos = find(tf_hasseg_ind_periodic < tloop, 1, 'last'); -% upperindpos = find(tf_hasseg_ind_periodic > tloop, 1, 'first'); -% -% lowerind = tf_hasseg_ind_periodic_wrap(lowerindpos); -% upperind = tf_hasseg_ind_periodic_wrap(upperindpos); -% -% % Interpolation weight -% -% iw = (tloop-tf_hasseg_ind_periodic(lowerindpos))/(tf_hasseg_ind_periodic(upperindpos)-tf_hasseg_ind_periodic(lowerindpos)); -% if interpolationtype==1 %if sinusoidal interpolation is chosen -% iw = 0.5*(1-cos(pi*iw)); -% end -% % -% % New scheme does only for selected slices % Perform interpolation for all slices -% % for sloop = selectedslices%1:Nsl -% % Convert segmentations to polar coordinates (R,Theta) -% lowerX = X(1:end-1,lowerind,sloop); -% lowerY = Y(1:end-1,lowerind,sloop); -% lower_mx = mean(lowerX); -% lower_my = mean(lowerY); -% lowerR = sqrt((lowerX - lower_mx).^2 + (lowerY - lower_my).^2); -% lowerT = atan2(lowerY-lower_my, lowerX-lower_mx); -% -% [~,I] = sort(lowerT); -% lowerRsort = lowerR(I); -% lowerTsort = lowerT(I); -% -% upperX = X(1:end-1,upperind,sloop); -% upperY = Y(1:end-1,upperind,sloop); -% upper_mx = mean(upperX); -% upper_my = mean(upperY); -% upperR = sqrt((upperX - upper_mx).^2 + (upperY - upper_my).^2); -% upperT = atan2(upperY-upper_my, upperX-upper_mx); -% -% [~,I] = sort(upperT); -% upperRsort = upperR(I); -% upperTsort = upperT(I); -% -% % Skip slices where we don't have stuff to interpolate from -% if any(isnan([lowerR' upperR' lowerT' upperT'])) -% continue -% end -% -% % Interpolate to normalized Theta range -% Npts = size(X, 1); -% Tnorm = linspace(-pi,pi, Npts); -% Tnorm = Tnorm(1:end-1); -% -% lowerRint = interp1([lowerTsort-2*pi; lowerTsort; lowerTsort+2*pi], ... -% [lowerRsort; lowerRsort; lowerRsort], Tnorm, 'linear'); -% upperRint = interp1([upperTsort-2*pi; upperTsort; upperTsort+2*pi], ... -% [upperRsort; upperRsort; upperRsort], Tnorm, 'linear'); -% -% % Perform interpolation -% midR = (1-iw)*lowerRint + iw*upperRint; -% mid_mx = (1-iw)*lower_mx + iw*upper_mx; -% mid_my = (1-iw)*lower_my + iw*upper_my; -% -% % Go back to cartesian -% segoutX = mid_mx + midR.*cos(Tnorm); -% segoutY = mid_my + midR.*sin(Tnorm); -% -% % A little smoothing -% segoutX = conv([segoutX segoutX segoutX], [1 1 1]/3, 'same'); -% segoutX = segoutX(Npts:(2*Npts-1)); -% -% segoutY = conv([segoutY segoutY segoutY], [1 1 1]/3, 'same'); -% segoutY = segoutY(Npts:(2*Npts-1)); -% -% % Store as periodic -% segoutX(Npts) = segoutX(1); -% segoutY(Npts) = segoutY(1); -% -% % Store -% -% switch segtodo -% case 1 %LV endocardium -% SET(no).EndoX(:,tloop,sloop) = segoutX; -% SET(no).EndoY(:,tloop,sloop) = segoutY; -% case 2 %LV epicardium -% SET(no).EpiX(:,tloop,sloop) = segoutX; -% SET(no).EpiY(:,tloop,sloop) = segoutY; -% case 3 %RV endocardium -% SET(no).RVEndoX(:,tloop,sloop) = segoutX; -% SET(no).RVEndoY(:,tloop,sloop) = segoutY; -% case 4 %RV epicardium -% SET(no).RVEpiX(:,tloop,sloop) = segoutX; -% SET(no).RVEpiY(:,tloop,sloop) = segoutY; -% end -% -% -% end -% end - myworkoff; segment('updatevolume'); -segment('updatemodeldisplay'); -drawfunctions('drawimageno'); -drawfunctions('drawallslices'); +drawfunctions('drawno',no) diff --git a/source/segmentcmrimage.png b/source/segmentcmrimage.png new file mode 100644 index 0000000..01047dc Binary files /dev/null and b/source/segmentcmrimage.png differ diff --git a/source/segmentctimage.png b/source/segmentctimage.png new file mode 100644 index 0000000..3b300b5 Binary files /dev/null and b/source/segmentctimage.png differ diff --git a/source/segmentgui.m b/source/segmentgui.m index 7cbb1f9..f5e7426 100644 --- a/source/segmentgui.m +++ b/source/segmentgui.m @@ -3,11 +3,11 @@ properties AxesTables = []; - SegmentMeasurements=[]; LVNO = []; RVNO = []; FlowNO = []; FlowROI = []; + fontsizeincm = []; end methods @@ -31,285 +31,335 @@ %---------------------------------------- function initpermanentplaceholder(varargin) %-------------------------------------- - g=varargin{1}; - - iconcell=cell(1,1); - iconcell{1,1}=myicon('database',g.Handles.permanenticonholder,g.Icons.config.database,'Open file loader',@() segment('fileopen_Callback'),0); - iconcell{1,end+1}=myicon('databaseadd',g.Handles.permanenticonholder,g.Icons.config.databaseadd,'Save to disc',... - @() filemenu('saveall_Callback'),0); -% iconcell{1,end+1}=myicon(g.Handles.permanenticonholder,g.Icons.config.connect,'Open PACS connection','pacs(''init_Callback'')',0); -% iconcell{1,end+1}=myicon(g.Handles.permanenticonholder,g.Icons.config.connectadd,'Save to PACS','filemenu(''savetopacs_Callback'')',0); - iconcell{1,end+1}=myicon('closeall',g.Handles.permanenticonholder,g.Icons.config.closeall,'Close all image stacks',@() segment('filecloseall_Callback'),0); - - iconcell{1,end+1}=myicon('panel1',g.Handles.permanenticonholder,g.Icons.config.panel1,'View one image panel',@() drawfunctions('drawimageview',[],[1,1]),1,1); - iconcell{1,end+1}=myicon('panel2',g.Handles.permanenticonholder,g.Icons.config.panel2,'View two image panels',@() drawfunctions('drawimageview',[],[1,2]),1,1); - iconcell{1,end+1}=myicon('panel2x1',g.Handles.permanenticonholder,g.Icons.config.panel2x1,'View two image panels',@() drawfunctions('drawimageview',[],[2,1]),1,1); - iconcell{1,end+1}=myicon('panel3x1',g.Handles.permanenticonholder,g.Icons.config.panel3x1,'View three image panels',@() drawfunctions('drawimageview',[],[3,1]),1,1); - iconcell{1,end+1}=myicon('panel3',g.Handles.permanenticonholder,g.Icons.config.panel3,'View three image panels',@() drawfunctions('drawimageview',[],[1,3]),1,1); - iconcell{1,end+1}=myicon('panel4',g.Handles.permanenticonholder,g.Icons.config.panel4,'View four image panels',@() drawfunctions('drawimageview',[],[2,2]),1,1); - iconcell{1,end+1}=myicon('panel6',g.Handles.permanenticonholder,g.Icons.config.panel6,'View six image panels',@() drawfunctions('drawimageview',[],[2,3]),1,1); - iconcell{1,end+1}=myicon('orthoview',g.Handles.permanenticonholder,g.Icons.config.orthoview,'Orthogonal view',@() segment('orthoview'),1,1); - iconcell{1,end+1}=myicon('saveview',g.Handles.permanenticonholder,g.Icons.config.saveview,'Save view',@() segmentview,0); - - iconcell{1,end+1}=myicon('viewone',g.Handles.permanenticonholder,g.Icons.config.viewone,'View one slice',@() segment('viewimage_Callback','one'),1,2); - iconcell{1,end+1}=myicon('viewall',g.Handles.permanenticonholder,g.Icons.config.viewall,'View all slices',@() segment('viewimage_Callback','montage'),1,2); - iconcell{1,end+1}=myicon('viewrow',g.Handles.permanenticonholder,g.Icons.config.viewrow,'View all slices in 2 rows',@() segment('viewimage_Callback','montagerow'),1,2); - - iconcell{1,end+1}=myicon('undo',g.Handles.permanenticonholder,g.Icons.config.undo,'Undo last operation',@() tools('undosegmentation_Callback'),0); - iconcell{1,end+1}=myicon('refresh',g.Handles.permanenticonholder,g.Icons.config.refresh,'Refresh image view',@() segment('viewrefreshall_Callback'),0); - - iconcell{1,end+1}=myicon('play',g.Handles.permanenticonholder,g.Icons.config.play,'Play movie of all image stacks',@() segment('playall_Callback'),2); - iconcell{1,end+1}=myicon('next',g.Handles.permanenticonholder,g.Icons.config.next,'Next time frame for all image stacks',@() segment('nextallframe_Callback'),0); - iconcell{1,end+1}=myicon('prev',g.Handles.permanenticonholder,g.Icons.config.prev,'Previous time frame for all image stacks',@() segment('previousallframe_Callback'),0); - iconcell{1,end+1}=myicon('faster',g.Handles.permanenticonholder,g.Icons.config.faster,'Faster frame rate',@() segment('fasterframerate_Callback'),0); - iconcell{1,end+1}=myicon('slower',g.Handles.permanenticonholder,g.Icons.config.slower,'Slower frame rate',@() segment('slowerframerate_Callback'),0); - - iconcell{1,end+1}=myicon('hideall',g.Handles.permanenticonholder,g.Icons.config.hideall,'Hide all overlays (segmentation, point, text,...)',@() segment('viewhideall_Callback'),2); - iconcell{1,end+1}=myicon('clearall',g.Handles.permanenticonholder,g.Icons.config.clearall,'Clear all segmentation in current image stack',@() segment('segmentclearall_Callback'),0); - iconcell{1,end+1}=myicon('clearalledes',g.Handles.permanenticonholder,g.Icons.config.clearalledes,'Clear all segmentation except in ED and ES',@() segment('segmentclearallbutsystolediastole_Callback'),0); - iconcell{1,end+1}=myicon('zoomin',g.Handles.permanenticonholder,g.Icons.config.zoomin,'Zoom in',@() segment('viewzoomin_Callback'),0); - iconcell{1,end+1}=myicon('zoomout',g.Handles.permanenticonholder,g.Icons.config.zoomout,'Zoom out',@() segment('viewzoomout_Callback'),0); - iconcell{1,end+1}=myicon('autozoom',g.Handles.permanenticonholder,g.Icons.config.autozoom,'Auto zoom',@() segment('autozoom'),0); - iconcell{1,end+1}=myicon('colorbar',g.Handles.permanenticonholder,g.Icons.config.colorbar,'Hide colorbar',@() segment('viewhidecolorbar_Callback'),2); - iconcell{1,end+1}=myicon('viewpixels',g.Handles.permanenticonholder,g.Icons.config.viewpixels,'Show image pixels',@() segment('viewinterp_Callback'),2); -% iconcell{1,end+1}=myicon('reportsheet',g.Handles.permanenticonholder,g.Icons.config.reportsheet,'Open Report sheet generation',@() reporter.reportsheet,0); - iconcell{1,end+1}=myicon('savescreen',g.Handles.permanenticonholder,g.Icons.config.savescreen,'Save screen shot',@() export('screenshot_Callback'),0); - - iconcell{1,end+1}=myicon('settingsgeneral',g.Handles.permanenticonholder,g.Icons.config.settingsgeneral,'Set general preferences',@() segpref,0); - iconcell{1,end+1}=myicon('settingssystem',g.Handles.permanenticonholder,g.Icons.config.settingsdatabase,'Set patient database preferences',@() segpref('advancedsettings_Callback'),0); - iconcell{1,end+1}=myicon('settingspacs',g.Handles.permanenticonholder,g.Icons.config.settingspacs,'Set PACS connection preferences',@() pacspref,0); - g.Handles.permanenticonholder.add(iconcell); + g = varargin{1}; - pos=plotboxpos(g.Handles.permanenticonholder.axeshandle); - currentpos=get(g.Handles.permanenticonholder.axeshandle,'position'); - set(g.Handles.permanenticonholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - set(g.Handles.iconuipanel,'visible','on') + gHnd = g.Handles; + gIcn = g.Icons.config; + iconcell = cell(1,1); + iconcell{1,1} = myicon('database',gHnd.permanenticonholder,gIcn.database,'Open from disc [Ctrl-O]',@() segment('fileopen_Callback'),0); + iconcell{1,end+1} = myicon('databaseadd',gHnd.permanenticonholder,gIcn.databaseadd,'Save to disc [Ctrl-S]',... + @() filemenu('saveall_Callback'),0); + iconcell{1,end+1} = myicon('closeall',gHnd.permanenticonholder,gIcn.closeall,'Close all image stacks [Ctrl-Shift-W]',@() segment('filecloseall_Callback'),0); + + iconcell{1,end+1} = myicon('panel1',gHnd.permanenticonholder,gIcn.panel1,'View one image panel [Shift-1]',@() viewfunctions('setview',1,1),1,1); + iconcell{1,end+1} = myicon('panel2',gHnd.permanenticonholder,gIcn.panel2,'View two image panels [Shift-2]',@() viewfunctions('setview',1,2),1,1); + iconcell{1,end+1} = myicon('panel2x1',gHnd.permanenticonholder,gIcn.panel2x1,'View two image panels [Alt-2]',@() viewfunctions('setview',2,1),1,1); + iconcell{1,end+1} = myicon('panel3x1',gHnd.permanenticonholder,gIcn.panel3x1,'View three image panels [Alt-3]',@() viewfunctions('setview',3,1),1,1); + iconcell{1,end+1} = myicon('panel3',gHnd.permanenticonholder,gIcn.panel3,'View three image panels [Shift-3]',@() viewfunctions('setview',1,3),1,1); + iconcell{1,end+1} = myicon('panel4',gHnd.permanenticonholder,gIcn.panel4,'View four image panels [Shift-4]',@() viewfunctions('setview',2,2),1,1); + iconcell{1,end+1} = myicon('panel6',gHnd.permanenticonholder,gIcn.panel6,'View six image panels [Shift-6]',@() viewfunctions('setview',2,3),1,1); + iconcell{1,end+1} = myicon('orthoview',gHnd.permanenticonholder,gIcn.orthoview,'Orthogonal view',@() callbackfunctions('orthoview_Callback'),1,1); + iconcell{1,end+1} = myicon('saveview',gHnd.permanenticonholder,gIcn.saveview,'Save view',@() segmentview,0); + + iconcell{1,end+1} = myicon('viewone',gHnd.permanenticonholder,gIcn.viewone,'View one slice [Ctrl-1]',@() viewfunctions('setviewtype','one'),1,2); + iconcell{1,end+1} = myicon('viewall',gHnd.permanenticonholder,gIcn.viewall,'View all slices [Ctrl-3]',@() viewfunctions('setviewtype','montage'),1,2); + iconcell{1,end+1} = myicon('viewrow',gHnd.permanenticonholder,gIcn.viewrow,'View all slices in 2 rows [Ctrl-4]',@() viewfunctions('setviewtype','montagerow'),1,2); + + iconcell{1,end+1} = myicon('undo',gHnd.permanenticonholder,gIcn.undo,'Undo last operation [Ctrl-Z]',@() tools('undosegmentation_Callback'),0); + iconcell{1,end+1} = myicon('refresh',gHnd.permanenticonholder,gIcn.refresh,'Refresh image view',@() viewfunctions('setview'),0); + + iconcell{1,end+1} = myicon('play',gHnd.permanenticonholder,gIcn.play,'Play movie [P]',@() callbackfunctions('play_Callback'),2); + iconcell{1,end+1} = myicon('next',gHnd.permanenticonholder,gIcn.next,'Next frame [Rigth arrow]',@() viewfunctions('switchtimeframe',1,true),0); + iconcell{1,end+1} = myicon('prev',gHnd.permanenticonholder,gIcn.prev,'Previous frame [Left arrow]',@() viewfunctions('switchtimeframe',-1,true),0); + iconcell{1,end+1} = myicon('faster',gHnd.permanenticonholder,gIcn.faster,'Faster frame rate',@() segment('fasterframerate_Callback'),0); + iconcell{1,end+1} = myicon('slower',gHnd.permanenticonholder,gIcn.slower,'Slower frame rate',@() segment('slowerframerate_Callback'),0); + + iconcell{1,end+1} = myicon('hideall',gHnd.permanenticonholder,gIcn.hideall,'Hide/show all overlays [H]',@() viewfunctions('viewhideall_Callback'),2); + iconcell{1,end+1} = myicon('clearall',gHnd.permanenticonholder,gIcn.clearall,'Clear all segmentation in current image stack',@() callbackfunctions('segmentclearall_Callback'),0); + iconcell{1,end+1} = myicon('clearalledes',gHnd.permanenticonholder,gIcn.clearalledes,'Clear all segmentation except in ED and ES',@() callbackfunctions('segmentclearallbutsystolediastole_Callback'),0); + iconcell{1,end+1} = myicon('zoomin',gHnd.permanenticonholder,gIcn.zoomin,'Zoom in [Ctrl-plus]',@() viewfunctions('zoom',1),0);%segment('viewzoomin_Callback'),0); + iconcell{1,end+1} = myicon('zoomout',gHnd.permanenticonholder,gIcn.zoomout,'Zoom out [Ctrl-minus]',@() viewfunctions('zoom',-1),0);%segment('viewzoomout_Callback'),0); + iconcell{1,end+1} = myicon('autozoom',gHnd.permanenticonholder,gIcn.autozoom,'Auto zoom',@() segment('autozoom'),0); + iconcell{1,end+1} = myicon('colorbar',gHnd.permanenticonholder,gIcn.colorbar,'Hide colorbar',@() viewfunctions('viewhidecolorbar_Callback'),2); + iconcell{1,end+1} = myicon('viewpixels',gHnd.permanenticonholder,gIcn.viewpixels,'Show image pixels',@() viewfunctions('viewinterp_Callback'),2); +% iconcell{1,end+1} = myicon('reportsheet',gHnd.permanenticonholder,gIcn.reportsheet,'Open Report sheet generation',@() reporter.reportsheet,0); + iconcell{1,end+1} = myicon('savescreen',gHnd.permanenticonholder,gIcn.savescreen,'Save screen shot',@() export('screenshot_Callback'),0); + + iconcell{1,end+1} = myicon('settingsgeneral',gHnd.permanenticonholder,gIcn.settingsgeneral,'Set general preferences',@() segpref,0); + iconcell{1,end+1} = myicon('settingssystem',gHnd.permanenticonholder,gIcn.settingsdatabase,'Set patient database preferences',@() segpref('advancedsettings_Callback'),0); + iconcell{1,end+1} = myicon('settingspacs',gHnd.permanenticonholder,gIcn.settingspacs,'Set PACS connection preferences',@() pacspref,0); + gHnd.permanenticonholder.add(iconcell); + + pos = plotboxpos(gHnd.permanenticonholder.axeshandle); + currentpos=get(gHnd.permanenticonholder.axeshandle,'position'); + set(gHnd.permanenticonholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); + set(gHnd.iconuipanel,'visible','on') end %--------------------------------------------- function initconfigplaceholder(varargin) - %-------------------------------------------- - g=varargin{1}; + %-------------------------------------------- + g = varargin{1}; + gHnd = g.Handles; + gIcn = g.Icons.config; - %check if using new gui version -% if all([isfield(g.Icons,'lviconcell'),isfield(g.Icons,'rviconcell'),... -% isfield(g.Icons,'analysisviconcell'),isfield(g.Icons,'roiflowiconcell'),... -% isfield(g.Icons,'viabilityiconcell'),isfield(g.Icons,'imageiconcell')]); -% -% g.lviconcell=cell(1,1); -% g.rviconcell=cell(1,1); -% g.analysisiconcell=cell(1,1); -% g.roiflowiconcell=cell(1,1); -% g.viabilityiconcell=cell(1,1); -% g.imageiconcell=cell(1,1); -% else %initcells - lviconcell=cell(1,1); - rviconcell=cell(1,1); - analysisiconcell=cell(1,1); - roiflowiconcell=cell(1,1); - viabilityiconcell=cell(1,1); - imageiconcell=cell(1,1); + lviconcell = cell(1,1); + rviconcell = cell(1,1); + strainiconcell = cell(1,1); + analysisiconcell = cell(1,1); + roiflowiconcell = cell(1,1); + viabilityiconcell = cell(1,1); + imageiconcell = cell(1,1); %LV - lviconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - lviconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour',@() updatetool('move')); - lviconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - lviconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - lviconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - lviconcell{1,end+1}=myicon('lvstack',g.Handles.configiconholder,g.Icons.config.lvstack,'Go to LV stack',@() segment('viewspecial_Callback','lv'),0); - lviconcell{1,end+1}=myicon('moveall',g.Handles.configiconholder,g.Icons.config.moveall,'Translate all contours',@() updatetool('moveall')); - lviconcell{1,end+1}=myicon('autolv',g.Handles.configiconholder,g.Icons.config.autolv,'Automatic LV segmentation',@() updatetool('autolv'),0); - lviconcell{1,end+1}=myicon('endopen',g.Handles.configiconholder,g.Icons.config.endopen,'Endo pen',@() updatetool('drawendo')); - lviconcell{1,end+1}=myicon('epipen',g.Handles.configiconholder,g.Icons.config.epipen,'Epi pen',@() updatetool('drawepi')); - lviconcell{1,end+1}=myicon('interpendo',g.Handles.configiconholder,g.Icons.config.interpendo,'Set interpolation points for Endo',@() updatetool('interpendo')); - lviconcell{1,end+1}=myicon('interpepi',g.Handles.configiconholder,g.Icons.config.interpepi,'Set interpolation points for Epi',@() updatetool('interpepi')); - lviconcell{1,end+1}=myicon('smooth',g.Handles.configiconholder,g.Icons.config.smooth,'Smooth latest contour (O)',@() tools('smoothsegmentation_Callback'),0); + lviconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + lviconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + lviconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + lviconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + lviconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + lviconcell{1,end+1} = myicon('lvstack',gHnd.configiconholder,gIcn.lvstack,'Go to LV stack',@() segment('viewspecial_Callback','lv'),0); + lviconcell{1,end+1} = myicon('selectoneall',gHnd.configiconholder,gIcn.selectoneall,'Select one or all frames mode [1]',@()segment_main('singleframemode_Callback'),2,1,gIcn.selectallone); + + lviconcell{1,end+1} = myicon('moveall',gHnd.configiconholder,gIcn.moveall,'Translate all contours',@() buttondownfunctions('updatebuttondowns','moveall')); + lviconcell{1,end+1} = myicon('autolv',gHnd.configiconholder,gIcn.autolv,'AI-based semi-automatic LV segmentation',@() lvsegmentationml,0); + % check if GPU available + if gpuDeviceCount > 0 + lviconcell{1,end+1} = myicon('autolvwand',gHnd.configiconholder,gIcn.autolvwand,'AI-based automatic LV segmentation [Ctrl-L]',@() lvsegmentationml('doaltlv2_Callback'),0); + else + lviconcell{1,end+1} = myicon('autolvedes',gHnd.configiconholder,gIcn.autolvedes,'AI-based automatic LV segmentation for ED/ES [Ctrl-L]',@() lvsegmentationml('doaltlv2_Callback',true),0); + end + lviconcell{1,end+1} = myicon('endopen',gHnd.configiconholder,gIcn.endopen,'Endo pen',@() buttondownfunctions('updatebuttondowns','Endo')); + lviconcell{1,end+1} = myicon('epipen',gHnd.configiconholder,gIcn.epipen,'Epi pen',@() buttondownfunctions('updatebuttondowns','Epi')); + lviconcell{1,end+1} = myicon('interpendo',gHnd.configiconholder,gIcn.interpendo,'Set interpolation points for Endo',@() buttondownfunctions('updatebuttondowns','EndoInterp')); + lviconcell{1,end+1} = myicon('interpepi',gHnd.configiconholder,gIcn.interpepi,'Set interpolation points for Epi',@() buttondownfunctions('updatebuttondowns','EpiInterp')); + lviconcell{1,end+1} = myicon('balloonendo',gHnd.configiconholder,gIcn.balloonendo,'Semi automatic Endo tool',@() buttondownfunctions('updatebuttondowns','EndoBalloon')); +% lviconcell{1,end+1} = myicon('balloonepi',gHnd.configiconholder,gIcn.balloonepi,'Semi automatic Epi tool',@() lvsegmentation('smartepi_Callback'),0); + lviconcell{1,end+1} = myicon('smooth',gHnd.configiconholder,gIcn.smooth,'Smooth current contour [O]',@() tools('smoothsegmentation_Callback'),0); - lviconcell{1,end+1}=myicon('interpseginslice',g.Handles.configiconholder,g.Icons.config.interpseginslice,'Interpolate segmentation over slices',@() lv('interpolatedelineation_Callback'),0); - lviconcell{1,end+1}=myicon('interpsegintime',g.Handles.configiconholder,g.Icons.config.interpsegintime,'Interpolate segmentation in time for selected slices',@() segmentation('interpolatedelineationovertime_Callback'),0); - lviconcell{1,end+1}=myicon('refineendo',g.Handles.configiconholder,g.Icons.config.refineendo,'Refine Endo',@() lvpeter('segmentrefineendo_Callback'),0); - lviconcell{1,end+1}=myicon('refineepi',g.Handles.configiconholder,g.Icons.config.refineepi,'Refine Epi',@() lvpeter('segmentrefineepi_Callback'),0); - lviconcell{1,end+1}=myicon('propagateendo',g.Handles.configiconholder,g.Icons.config.propagateendo,'Propagate endo forward in time', @() lvpeter('segmentpropagateendo_Callback'),0); - lviconcell{1,end+1}=myicon('propagateepi',g.Handles.configiconholder,g.Icons.config.propagateepi,'Propagate epi forward in time',@() lvpeter('segmentpropagateepi_Callback'),0); - - lviconcell{1,end+1}=myicon('contractendo',g.Handles.configiconholder,g.Icons.config.contractendo,'Contract Endo segmentation',@() lv('segmentexpandcontract_Callback',-1,'endo'),0); - lviconcell{1,end+1}=myicon('expandendo',g.Handles.configiconholder,g.Icons.config.expandendo,'Expand Endo segmentation',@() lv('segmentexpandcontract_Callback',1,'endo'),0); - lviconcell{1,end+1}=myicon('contractepi',g.Handles.configiconholder,g.Icons.config.contractepi,'Contract Epi segmentation',@() lv('segmentexpandcontract_Callback',-1,'epi'),0); - lviconcell{1,end+1}=myicon('expandepi',g.Handles.configiconholder,g.Icons.config.expandepi,'Expand Epi segmentation',@() lv('segmentexpandcontract_Callback',1,'epi'),0); - lviconcell{1,end+1}=myicon('evenoutwall',g.Handles.configiconholder,g.Icons.config.evenoutwall,'Even out wall',@() segment('smoothendowall_Callback'),0); - lviconcell{1,end+1}=myicon('copylvup',g.Handles.configiconholder,g.Icons.config.copylvup,'Copy LV upwards and refine',@()tools('copyupward_Callback'),0); - lviconcell{1,end+1}=myicon('copylvdown',g.Handles.configiconholder,g.Icons.config.copylvdown,'Copy LV downwards and refine',@()tools('copydownward_Callback'),0); + lviconcell{1,end+1} = myicon('interpseginslice',gHnd.configiconholder,gIcn.interpseginslice,'Interpolate segmentation over slices',@() lv('interpolatedelineation_Callback'),0); + lviconcell{1,end+1} = myicon('interpsegintime',gHnd.configiconholder,gIcn.interpsegintime,'Interpolate segmentation in time for selected slices',@() segmentation('interpolatedelineationovertime_Callback'),0); + lviconcell{1,end+1} = myicon('refineendo',gHnd.configiconholder,gIcn.refineendo,'Refine LV Endo [Ctrl-R]',@() lvpeter('segmentrefineendo_Callback'),0); + lviconcell{1,end+1} = myicon('refineepi',gHnd.configiconholder,gIcn.refineepi,'Refine LV Epi [Ctrl-Shift-R]',@() lvpeter('segmentrefineepi_Callback'),0); + lviconcell{1,end+1} = myicon('propagateendo',gHnd.configiconholder,gIcn.propagateendo,'Propagate LV Endo forward and refine [Ctrl-F]', @() lvpeter('segmentpropagateendo_Callback'),0); + lviconcell{1,end+1} = myicon('propagateepi',gHnd.configiconholder,gIcn.propagateepi,'Propagate LV Epi forward and refine [Ctrl-Shift-F]',@() lvpeter('segmentpropagateepi_Callback'),0); + + lviconcell{1,end+1} = myicon('contractendo',gHnd.configiconholder,gIcn.contractendo,'Contract LV Endo [Ctrl-K]',@() lv('segmentexpandcontract_Callback',-1,'endo'),0); + lviconcell{1,end+1} = myicon('expandendo',gHnd.configiconholder,gIcn.expandendo,'Expand LV Endo [Ctrl-E]',@() lv('segmentexpandcontract_Callback',1,'endo'),0); + lviconcell{1,end+1} = myicon('contractepi',gHnd.configiconholder,gIcn.contractepi,'Contract LV Epi [Ctrl-Alt-K]',@() lv('segmentexpandcontract_Callback',-1,'epi'),0); + lviconcell{1,end+1} = myicon('expandepi',gHnd.configiconholder,gIcn.expandepi,'Expand LV Epi [Ctrl-Alt-E]',@() lv('segmentexpandcontract_Callback',1,'epi'),0); + lviconcell{1,end+1} = myicon('evenoutwall',gHnd.configiconholder,gIcn.evenoutwall,'Even out myocardium wall [Alt-Up]',@() segment('smoothendowall_Callback'),0); + lviconcell{1,end+1} = myicon('copylvup',gHnd.configiconholder,gIcn.copylvup,'Copy LV upwards and refine [Ctrl-U]',@()tools('copyupward_Callback'),0); + lviconcell{1,end+1} = myicon('copylvdown',gHnd.configiconholder,gIcn.copylvdown,'Copy LV downwards and refine [Ctrl-D]',@()tools('copydownward_Callback'),0); - lviconcell{1,end+1}=myicon('hidelv',g.Handles.configiconholder,g.Icons.config.hidelv,'Hide LV segmentation',@() segment('viewhidelv_Callback'),2); - lviconcell{1,end+1}=myicon('hideinterp',g.Handles.configiconholder,g.Icons.config.hideinterp,'Hide interpolation points',@() segment('viewhideinterp_Callback'),2); - lviconcell{1,end+1}=myicon('clearalllv',g.Handles.configiconholder,g.Icons.config.clearalllv,'Clear all LV segmentation',@() segment('segmentclearalllv_Callback'),0); - lviconcell{1,end+1}=myicon('clearendo',g.Handles.configiconholder,g.Icons.config.clearendo,'Clear LV endo in selected slices according to mode',@() segmentation('clearslicesthis_Callback',1,0,0,0),0); - lviconcell{1,end+1}=myicon('clearepi',g.Handles.configiconholder,g.Icons.config.clearepi,'Clear LV epi in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,1,0,0),0); - lviconcell{1,end+1}=myicon('volumecurve',g.Handles.configiconholder,g.Icons.config.volumecurve,'Plot Volume Curve',@() lvpeter('plotvolumecurve'),0); + lviconcell{1,end+1} = myicon('hidelv',gHnd.configiconholder,gIcn.hidelv,'Hide LV segmentation',@() viewfunctions('hide_Callback'),2); + lviconcell{1,end+1} = myicon('hideinterp',gHnd.configiconholder,gIcn.hideinterp,'Hide interpolation points',@() viewfunctions('hide_Callback'),2); + lviconcell{1,end+1} = myicon('clearalllv',gHnd.configiconholder,gIcn.clearalllv,'Clear all LV segmentation',@() callbackfunctions('segmentclearalllv_Callback'),0); + lviconcell{1,end+1} = myicon('clearendo',gHnd.configiconholder,gIcn.clearendo,'Clear LV Endo in selected slices according to mode',@() segmentation('clearslicesthis_Callback',1,0,0,0),0); + lviconcell{1,end+1} = myicon('clearepi',gHnd.configiconholder,gIcn.clearepi,'Clear LV Epi in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,1,0,0),0); + lviconcell{1,end+1} = myicon('volumecurve',gHnd.configiconholder,gIcn.volumecurve,'Plot volume curve',@() lvpeter('plotvolumecurve'),0); - g.Icons.lviconcell=lviconcell; + g.Icons.lviconcell = lviconcell; %RV - rviconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - rviconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour', @() updatetool('move')); - rviconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - rviconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - rviconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - rviconcell{1,end+1}=myicon('rvstack',g.Handles.configiconholder,g.Icons.config.rvstack,'Go to RV stack',@() segment('viewspecial_Callback','rv'),0); - rviconcell{1,end+1} = lviconcell{1,7}; %moveall - rviconcell{1,end+1}=myicon('autorvendo',g.Handles.configiconholder,g.Icons.config.autorvendo,'Automatic RV Endo segmentation',@() updatetool('autorvendo'),0); - rviconcell{1,end+1}=myicon('rvendopen',g.Handles.configiconholder,g.Icons.config.rvendopen,'RV Endo pen',@() updatetool('drawrvendo')); - rviconcell{1,end+1}=myicon('rvepipen',g.Handles.configiconholder,g.Icons.config.rvepipen,'RV Epi pen',@() updatetool('drawrvepi')); - rviconcell{1,end+1}=myicon('interprvendo',g.Handles.configiconholder,g.Icons.config.interprvendo,'Set interpolation points for RV Endo',@() updatetool('interprvendo')); - rviconcell{1,end+1}=myicon('interprvepi',g.Handles.configiconholder,g.Icons.config.interprvepi,'Set interpolation points for RV Epi',@() updatetool('interprvepi')); - rviconcell{1,end+1}=myicon('refinervendo',g.Handles.configiconholder,g.Icons.config.refinervendo,'Refine RV Endo',@() rv('segmentrefinervendo_Callback'),0); + rviconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + rviconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour', @() buttondownfunctions('updatebuttondowns','move')); + rviconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + rviconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + rviconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + rviconcell{1,end+1} = myicon('rvstack',gHnd.configiconholder,gIcn.rvstack,'Go to RV stack',@() segment('viewspecial_Callback','rv'),0); + rviconcell{1,end+1} = lviconcell{1,7}; + + rviconcell{1,end+1} = lviconcell{1,8}; %moveall + rviconcell{1,end+1} = myicon('autorvendo',gHnd.configiconholder,gIcn.autorvendo,'Automatic RV Endo segmentation [Ctrl-Alt-M]',@() rvsegmentation,0); + rviconcell{1,end+1} = myicon('rvendopen',gHnd.configiconholder,gIcn.rvendopen,'RV Endo pen',@() buttondownfunctions('updatebuttondowns','RVEndo')); + rviconcell{1,end+1} = myicon('rvepipen',gHnd.configiconholder,gIcn.rvepipen,'RV Epi pen',@() buttondownfunctions('updatebuttondowns','RVEpi')); + rviconcell{1,end+1} = myicon('interprvendo',gHnd.configiconholder,gIcn.interprvendo,'Set interpolation points for RV Endo',@() buttondownfunctions('updatebuttondowns','RVEndoInterp')); + rviconcell{1,end+1} = myicon('interprvepi',gHnd.configiconholder,gIcn.interprvepi,'Set interpolation points for RV Epi',@() buttondownfunctions('updatebuttondowns','RVEpiInterp')); + rviconcell{1,end+1} = myicon('balloonrvendo',gHnd.configiconholder,gIcn.balloonrvendo,'Semi automatic RV Endo tool',@() buttondownfunctions('updatebuttondowns','RVEndoBalloon')); + rviconcell{1,end+1} = myicon('refinervendo',gHnd.configiconholder,gIcn.refinervendo,'Refine RV Endo [Ctrl-Alt-R]',@() rv('segmentrefinervendo_Callback'),0); %need icon - rviconcell{1,end+1}=myicon('copyrvup',g.Handles.configiconholder,g.Icons.config.copyrvup,'Copy RV endo upwards',@()tools('copyupward_Callback','endo',false,false),0); - rviconcell{1,end+1}=myicon('copyrvdown',g.Handles.configiconholder,g.Icons.config.copyrvdown,'Copy RV endo downwards',@()tools('copydownward_Callback','endo',false,false),0); + rviconcell{1,end+1} = myicon('copyrvup',gHnd.configiconholder,gIcn.copyrvup,'Copy RV Endo upwards and refine [Ctrl-Alt-U]',@()tools('copyupward_Callback','rvendo',false,false),0); + rviconcell{1,end+1} = myicon('copyrvdown',gHnd.configiconholder,gIcn.copyrvdown,'Copy RV Endo downwards and refine [Ctrl-Alt-D]',@()tools('copydownward_Callback','rvendo',false,false),0); - rviconcell{1,end+1}=myicon('interpsegintime',g.Handles.configiconholder,g.Icons.config.interpsegintime,'Interpolate segmentation in time',@() segmentation('interpolatedelineationovertime_Callback'),0); - rviconcell{1,end+1}=myicon('interpseginslice',g.Handles.configiconholder,g.Icons.config.interpseginslice,'Interpolate segmentation over slices',@() lv('interpolatedelineation_Callback'),0); + rviconcell{1,end+1} = myicon('interpsegintime',gHnd.configiconholder,gIcn.interpsegintime,'Interpolate segmentation in time',@() segmentation('interpolatedelineationovertime_Callback'),0); + rviconcell{1,end+1} = myicon('interpseginslice',gHnd.configiconholder,gIcn.interpseginslice,'Interpolate segmentation over slices',@() lv('interpolatedelineation_Callback'),0); - rviconcell{1,end+1}=myicon('hiderv',g.Handles.configiconholder,g.Icons.config.hiderv,'Hide RV segmentation', @() segment('viewhiderv_Callback'),2); - rviconcell{1,end+1}=lviconcell{end-4};%myicon('hideinterp',g.Handles.configiconholder,g.Icons.config.hideinterp,'Hide interpolation points',@() segment('viewhideinterp_Callback'),2); - rviconcell{1,end+1}=myicon('clearallrv',g.Handles.configiconholder,g.Icons.config.clearallrv,'Clear all RV segmentation',@() segment('segmentclearallrv_Callback'),0); - rviconcell{1,end+1}=myicon('clearrvendo',g.Handles.configiconholder,g.Icons.config.clearrv,'Clear RV endo in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,0,1,0),0); - rviconcell{1,end+1}=myicon('clearrvepi',g.Handles.configiconholder,g.Icons.config.clearrvepi,'Clear RV epi in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,0,0,1),0); - rviconcell{1,end+1}=myicon('volumecurve',g.Handles.configiconholder,g.Icons.config.volumecurve,'Plot Volume Curve',@() lvpeter('plotvolumecurve'),0); + rviconcell{1,end+1} = myicon('hiderv',gHnd.configiconholder,gIcn.hiderv,'Hide RV segmentation', @() viewfunctions('hide_Callback'),2); + rviconcell{1,end+1} = lviconcell{end-4};%myicon('hideinterp',gHnd.configiconholder,gIcn.hideinterp,'Hide interpolation points',@() segment('viewhideinterp_Callback'),2); + rviconcell{1,end+1} = myicon('clearallrv',gHnd.configiconholder,gIcn.clearallrv,'Clear all RV segmentation',@() callbackfunctions('segmentclearallrv_Callback'),0); + rviconcell{1,end+1} = myicon('clearrvendo',gHnd.configiconholder,gIcn.clearrv,'Clear RV endo in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,0,1,0),0); + rviconcell{1,end+1} = myicon('clearrvepi',gHnd.configiconholder,gIcn.clearrvepi,'Clear RV epi in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,0,0,1),0); + rviconcell{1,end+1} = myicon('volumecurve',gHnd.configiconholder,gIcn.volumecurve,'Plot volume curve',@() lvpeter('plotvolumecurve'),0); - g.Icons.rviconcell=rviconcell; + g.Icons.rviconcell = rviconcell; %ROIFLOW - roiflowiconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - roiflowiconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour',@() updatetool('move')); - roiflowiconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - %roiflowiconcell{1,end+1}=myicon('scaleROI',g.Handles.configiconholder,g.Icons.config.scaleROI,'Scale ROI',@() updatetool('scaleROI')); - roiflowiconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - roiflowiconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - roiflowiconcell{1,end+1}=myicon('flowstack',g.Handles.configiconholder,g.Icons.config.flowstack,'Go to flow stack',@() segment('viewspecial_Callback','flow'),0); - roiflowiconcell{1,end+1}=myicon('putroi',g.Handles.configiconholder,g.Icons.config.putroi,'Place ROI',@() updatetool('putroi')); - roiflowiconcell{1,end+1}=myicon('roipen',g.Handles.configiconholder,g.Icons.config.roipen,'ROI pen',@() updatetool('drawroi')); - roiflowiconcell{1,end+1}=myicon('roipen',g.Handles.configiconholder,g.Icons.config.trackingvessel,'Track vessel in all time frames',@() vesselsnake_flowtrackroi('flowtrackroi'),0); - roiflowiconcell{1,end+1}=myicon('refineroi',g.Handles.configiconholder,g.Icons.config.refineroi,'Refine ROI',@() flow('flowrefine_Callback'),0); - roiflowiconcell{1,end+1}=myicon('refineroinext',g.Handles.configiconholder,g.Icons.config.refineroinext,'Propagate ROI to next timeframe',@() flow('flowpropagate_Callback'),0); - roiflowiconcell{1,end+1}=myicon('contractroi',g.Handles.configiconholder,g.Icons.config.contractroi,'Contract ROI',@() roi('expandcontract_Callback',-1),0); - roiflowiconcell{1,end+1}=myicon('expandroi',g.Handles.configiconholder,g.Icons.config.expandroi,'Expand ROI',@() roi('expandcontract_Callback',1),0); - roiflowiconcell{1,end+1}=myicon('unwrap',g.Handles.configiconholder,g.Icons.config.unwrap,'Unwrap flow',@() flowunwrap,0); - roiflowiconcell{1,end+1}=myicon('palette',g.Handles.configiconholder,g.Icons.config.palette,'Set ROI color',@() roi('roisetcolor_Callback'),0); - roiflowiconcell{1,end+1}=myicon('text',g.Handles.configiconholder,g.Icons.config.text,'Set ROI label',@() roi('roisetlabel_Callback'),0); - roiflowiconcell{1,end+1}=myicon('plotflow',g.Handles.configiconholder,g.Icons.config.plotflow,'Plot flow',@() reportflow,0); - roiflowiconcell{1,end+1}=myicon('hideroi',g.Handles.configiconholder,g.Icons.config.hideroi,'Hide ROI',@() segment('viewhideroi_Callback'),2); - roiflowiconcell{1,end+1}=myicon('clearroi',g.Handles.configiconholder,g.Icons.config.clearroi,'Clear selected ROIs',@() roi('roidelete_Callback'),0); - roiflowiconcell{1,end+1}=myicon('clearallroi',g.Handles.configiconholder,g.Icons.config.clearallroi,'Clear all ROIs',@() roi('roiclearall_Callback'),0); - g.Icons.roiflowiconcell=roiflowiconcell; + roiflowiconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + roiflowiconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + roiflowiconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + %roiflowiconcell{1,end+1} = myicon('scaleROI',gHnd.configiconholder,gIcn.scaleROI,'Scale ROI',@() updatetool('scaleROI')); + roiflowiconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + roiflowiconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + roiflowiconcell{1,end+1} = myicon('flowstack',gHnd.configiconholder,gIcn.flowstack,'Go to flow stack',@() segment('viewspecial_Callback','flow'),0); + roiflowiconcell{1,end+1} = lviconcell{1,7}; + + roiflowiconcell{1,end+1} = myicon('putroi',gHnd.configiconholder,gIcn.putroi,'Place ROI',@() buttondownfunctions('updatebuttondowns','RoiPut')); + roiflowiconcell{1,end+1} = myicon('roipen',gHnd.configiconholder,gIcn.roipen,'ROI pen',@() buttondownfunctions('updatebuttondowns','Roi')); + roiflowiconcell{1,end+1} = myicon('balloonroi',gHnd.configiconholder,gIcn.balloonroi,'Semi automatic ROI tool',@() buttondownfunctions('updatebuttondowns','RoiBalloon')); + roiflowiconcell{1,end+1} = myicon('trackingvessel',gHnd.configiconholder,gIcn.trackingvessel,'Track vessel over time [Alt-T]',@() vesselsnake_flowtrackroi('flowtrackroi'),0); + roiflowiconcell{1,end+1} = myicon('refineroi',gHnd.configiconholder,gIcn.refineroi,'Refine Flow ROI [Alt-R]',@() flow('flowrefine_Callback'),0); + roiflowiconcell{1,end+1} = myicon('refineroinext',gHnd.configiconholder,gIcn.refineroinext,'Propagate Flow ROI forward and refine [Alt-F]',@() flow('flowpropagate_Callback'),0); + roiflowiconcell{1,end+1} = myicon('contractroi',gHnd.configiconholder,gIcn.contractroi,'Contract ROI',@() roi('expandcontract_Callback',-1),0); + roiflowiconcell{1,end+1} = myicon('expandroi',gHnd.configiconholder,gIcn.expandroi,'Expand ROI',@() roi('expandcontract_Callback',1),0); + roiflowiconcell{1,end+1} = myicon('unwrap',gHnd.configiconholder,gIcn.unwrap,'Unwrap flow',@() flowunwrap,0); + roiflowiconcell{1,end+1} = myicon('palette',gHnd.configiconholder,gIcn.palette,'Set ROI color',@() roi('roisetcolor_Callback'),0); + roiflowiconcell{1,end+1} = myicon('text',gHnd.configiconholder,gIcn.text,'Set ROI label',@() roi('roisetlabel_Callback'),0); + roiflowiconcell{1,end+1} = myicon('plotflow',gHnd.configiconholder,gIcn.plotflow,'Plot flow [Ctrl-T]',@() reportflow,0); + roiflowiconcell{1,end+1} = myicon('hideroi',gHnd.configiconholder,gIcn.hideroi,'Hide ROI',@() viewfunctions('hide_Callback'),2); + roiflowiconcell{1,end+1} = myicon('hidetext',gHnd.configiconholder,gIcn.hidetext,'Hide text',@() viewfunctions('hide_Callback'),2); + roiflowiconcell{1,end+1} = myicon('clearroi',gHnd.configiconholder,gIcn.clearroi,'Clear selected ROIs',@() roi('roidelete_Callback'),0); + roiflowiconcell{1,end+1} = myicon('clearallroi',gHnd.configiconholder,gIcn.clearallroi,'Clear all ROIs',@() roi('roiclearall_Callback'),0); + g.Icons.roiflowiconcell = roiflowiconcell; %Viablility - viabilityiconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - viabilityiconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour',@() updatetool('move')); - viabilityiconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - viabilityiconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - viabilityiconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - viabilityiconcell{1,end+1}=myicon('scarstack',g.Handles.configiconholder,g.Icons.config.scarstack,'Go to scar stack',@() segment('viewspecial_Callback','cinescar'),0); - viabilityiconcell{1,end+1}=myicon('importfromother',g.Handles.configiconholder,g.Icons.config.importfromother,'Import LV segmentation from cine to scar image stack',@() segmentation('importfromcine2scar_Callback'),0); - viabilityiconcell{1,end+1}=myicon('moveall',g.Handles.configiconholder,g.Icons.config.moveall,'Translate all contours',@() updatetool('moveall')); - viabilityiconcell{1,end+1}=myicon('endopen',g.Handles.configiconholder,g.Icons.config.endopen,'Endo pen',@() updatetool('drawendo')); - viabilityiconcell{1,end+1}=myicon('epipen',g.Handles.configiconholder,g.Icons.config.epipen,'Epi pen',@() updatetool('drawepi')); - viabilityiconcell{1,end+1}=myicon('interpendo',g.Handles.configiconholder,g.Icons.config.interpendo,'Set interpolation points for Endo',@() updatetool('interpendo')); - viabilityiconcell{1,end+1}=myicon('interpepi',g.Handles.configiconholder,g.Icons.config.interpepi,'Set interpolation points for Epi',@() updatetool('interpepi')); - viabilityiconcell{1,end+1}=myicon('autoscar',g.Handles.configiconholder,g.Icons.config.autoscar,'Auto scar',@() updatetool('autoscar'),0); - viabilityiconcell{1,end+1}=myicon('scarpen',g.Handles.configiconholder,g.Icons.config.scarpen,'Draw scar',@() updatetool('drawscar')); - viabilityiconcell{1,end+1}=myicon('mopen',g.Handles.configiconholder,g.Icons.config.mopen,'Draw MO',@() updatetool('drawmo')); - viabilityiconcell{1,end+1}=myicon('rubberscar',g.Handles.configiconholder,g.Icons.config.rubberscar,'Manually remove scar segmentation',@() updatetool('drawrubberpen')); - viabilityiconcell{1,end+1}=myicon('automar',g.Handles.configiconholder,g.Icons.config.automar,'Auto MaR',@() updatetool('automar'),0); - viabilityiconcell{1,end+1}=myicon('marpen',g.Handles.configiconholder,g.Icons.config.marpen,'Draw MaR',@() updatetool('drawmarpen')); - viabilityiconcell{1,end+1}=myicon('rubbermar',g.Handles.configiconholder,g.Icons.config.rubbermar,'Manually remove MaR segmentation',@() updatetool('drawmarrubberpen')); - viabilityiconcell{1,end+1}=myicon('hidescar',g.Handles.configiconholder,g.Icons.config.hidescar,'Hide scar segmentation',@() segment('viewhidescar_Callback'),2); - viabilityiconcell{1,end+1}=myicon('hidescarextent',g.Handles.configiconholder,g.Icons.config.hidescarextent,'Hide scar segmentation extent',@() segment('viewhidescarextent_Callback'),2); - viabilityiconcell{1,end+1}=myicon('hidescarmanual',g.Handles.configiconholder,g.Icons.config.hidescarmanual,'Hide manual scar interaction',@() segment('viewhidemanualinteraction_Callback'),2); - viabilityiconcell{1,end+1}=myicon('hidemar',g.Handles.configiconholder,g.Icons.config.hidemar,'Hide MaR segmentation',@() segment('viewhidemar_Callback'),2); - viabilityiconcell{1,end+1}=myicon('clearscar',g.Handles.configiconholder,g.Icons.config.clearscar,'Clear scar segmentation',@() viability('viabilityclear_Callback'),0); - viabilityiconcell{1,end+1}=myicon('clearmar',g.Handles.configiconholder,g.Icons.config.clearmar,'Clear MaR segmentation',@() mar('clearall_Callback'),0); - g.Icons.viabilityiconcell=viabilityiconcell; + viabilityiconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + viabilityiconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + viabilityiconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + viabilityiconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + viabilityiconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + viabilityiconcell{1,end+1} = myicon('scarstack',gHnd.configiconholder,gIcn.scarstack,'Go to scar stack',@() segment('viewspecial_Callback','cinescar'),0); + viabilityiconcell{1,end+1} = lviconcell{1,7}; + + viabilityiconcell{1,end+1} = myicon('importfromother',gHnd.configiconholder,gIcn.importfromother,'Import LV segmentation from cine to scar image stack',@() segmentation('importfromcine2scar_Callback'),0); + viabilityiconcell{1,end+1} = myicon('moveall',gHnd.configiconholder,gIcn.moveall,'Translate all contours',@() buttondownfunctions('updatebuttondowns','moveall')); + viabilityiconcell{1,end+1} = myicon('endopen',gHnd.configiconholder,gIcn.endopen,'Endo pen',@() buttondownfunctions('updatebuttondowns','Endo')); + viabilityiconcell{1,end+1} = myicon('epipen',gHnd.configiconholder,gIcn.epipen,'Epi pen',@() buttondownfunctions('updatebuttondowns','Epi')); + viabilityiconcell{1,end+1} = myicon('interpendo',gHnd.configiconholder,gIcn.interpendo,'Set interpolation points for Endo',@() buttondownfunctions('updatebuttondowns','EndoInterp')); + viabilityiconcell{1,end+1} = myicon('interpepi',gHnd.configiconholder,gIcn.interpepi,'Set interpolation points for Epi',@() buttondownfunctions('updatebuttondowns','EpiInterp')); + viabilityiconcell{1,end+1} = myicon('autoscar',gHnd.configiconholder,gIcn.autoscar,'Auto scar',@() viability('viabilityautoewa'),0); + viabilityiconcell{1,end+1} = myicon('scarpen',gHnd.configiconholder,gIcn.scarpen,'Draw scar',@() buttondownfunctions('updatebuttondowns','Scar')); + viabilityiconcell{1,end+1} = myicon('mopen',gHnd.configiconholder,gIcn.mopen,'Draw MO',@() buttondownfunctions('updatebuttondowns','MO')); + viabilityiconcell{1,end+1} = myicon('rubberscar',gHnd.configiconholder,gIcn.rubberscar,'Manually remove scar segmentation',@() buttondownfunctions('updatebuttondowns','ScarRubber')); + viabilityiconcell{1,end+1} = myicon('automar',gHnd.configiconholder,gIcn.automar,'Auto MaR',@() mar('auto_Callback'),0); + viabilityiconcell{1,end+1} = myicon('marpen',gHnd.configiconholder,gIcn.marpen,'Draw MaR',@() buttondownfunctions('updatebuttondowns','MaR')); + viabilityiconcell{1,end+1} = myicon('rubbermar',gHnd.configiconholder,gIcn.rubbermar,'Manually remove MaR segmentation',@() buttondownfunctions('updatebuttondowns','MaRRubber')); + viabilityiconcell{1,end+1} = myicon('hidescar',gHnd.configiconholder,gIcn.hidescar,'Hide scar segmentation',@() viewfunctions('hide_Callback'),2); + viabilityiconcell{1,end+1} = myicon('hidescarextent',gHnd.configiconholder,gIcn.hidescarextent,'Hide scar segmentation extent',@() viewfunctions('hide_Callback'),2); + viabilityiconcell{1,end+1} = myicon('hidescarmanual',gHnd.configiconholder,gIcn.hidescarmanual,'Hide manual scar interaction',@() viewfunctions('viewhidemanualinteraction_Callback'),2); + viabilityiconcell{1,end+1} = myicon('hidemar',gHnd.configiconholder,gIcn.hidemar,'Hide MaR segmentation',@() viewfunctions('hide_Callback'),2); + viabilityiconcell{1,end+1} = myicon('clearscar',gHnd.configiconholder,gIcn.clearscar,'Clear scar segmentation',@() viability('viabilityclear_Callback'),0); + viabilityiconcell{1,end+1} = myicon('clearmar',gHnd.configiconholder,gIcn.clearmar,'Clear MaR segmentation',@() mar('clearall_Callback'),0); + g.Icons.viabilityiconcell = viabilityiconcell; + + %Strain + strainiconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + strainiconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + strainiconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + strainiconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + strainiconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + strainiconcell{1,end+1} = myicon('strainsaxstack',gHnd.configiconholder,gIcn.strainsaxstack,'Go to Strain SAX stack',@() segment('viewspecial_Callback','strainsax'),0); + strainiconcell{1,end+1} = myicon('strainlaxstack',gHnd.configiconholder,gIcn.strainlaxstack,'Go to Strain LAX stack',@() segment('viewspecial_Callback','strainlax'),0); + strainiconcell{1,end+1} = lviconcell{1,7}; + + strainiconcell{1,end+1} = myicon('crop',gHnd.configiconholder,gIcn.crop,'Manual crop',@() buttondownfunctions('updatebuttondowns','crop')); + strainiconcell{1,end+1} = myicon('drawingguide',gHnd.configiconholder,gIcn.drawingguide,'Drawing guidance for strain analysis',@() straintagging.straintagging('draw_guide_helper',[],0,1),0); + strainiconcell{1,end+1} = myicon('endopen',gHnd.configiconholder,gIcn.endopen,'Endo pen',@() buttondownfunctions('updatebuttondowns','Endo')); + strainiconcell{1,end+1} = myicon('epipen',gHnd.configiconholder,gIcn.epipen,'Epi pen',@() buttondownfunctions('updatebuttondowns','Epi')); + strainiconcell{1,end+1} = myicon('interpendo',gHnd.configiconholder,gIcn.interpendo,'Set interpolation points for Endo',@() buttondownfunctions('updatebuttondowns','EndoInterp')); + strainiconcell{1,end+1} = myicon('interpepi',gHnd.configiconholder,gIcn.interpepi,'Set interpolation points for Epi',@() buttondownfunctions('updatebuttondowns','EpiInterp')); + strainiconcell{1,end+1} = myicon('balloonendo',gHnd.configiconholder,gIcn.balloonendo,'Semi automatic Endo tool',@() buttondownfunctions('updatebuttondowns','EndoBalloon')); +% strainiconcell{1,end+1} = myicon('balloonepi',gHnd.configiconholder,gIcn.balloonepi,'Semi automatic Epi tool',@() lvsegmentation('smartepi_Callback'),0); + strainiconcell{1,end+1} = myicon('rvendopen',gHnd.configiconholder,gIcn.rvendopen,'RV Endo pen',@() buttondownfunctions('updatebuttondowns','RVEndo')); + strainiconcell{1,end+1} = myicon('interprvendo',gHnd.configiconholder,gIcn.interprvendo,'Set interpolation points for RV Endo',@() buttondownfunctions('updatebuttondowns','RVEndoInterp')); + strainiconcell{1,end+1} = myicon('smooth',gHnd.configiconholder,gIcn.smooth,'Smooth current contour [O]',@() tools('smoothsegmentation_Callback'),0); + strainiconcell{1,end+1} = myicon('point',gHnd.configiconholder,gIcn.point,'Place annotation point',@() buttondownfunctions('updatebuttondowns','Point')); + strainiconcell{1,end+1} = myicon('strainftsax',gHnd.configiconholder,gIcn.strainftsaxanalysis,'Start FT Strain SAX analysis',@() straintagging.straintagging('init','cine','shortaxis'),0); + strainiconcell{1,end+1} = myicon('strainftlax',gHnd.configiconholder,gIcn.strainftlaxanalysis,'Start FT Strain LAX analysis',@() straintagging.straintagging('init','cine','longaxis'),0); + strainiconcell{1,end+1} = myicon('straintagsax',gHnd.configiconholder,gIcn.straintagsaxanalysis,'Start Tagging Strain SAX analysis',@() straintagging.straintagging('init','tagging','shortaxis'),0); + strainiconcell{1,end+1} = myicon('straintaglax',gHnd.configiconholder,gIcn.straintaglaxanalysis,'Start Tagging Strain LAX analysis',@() straintagging.straintagging('init','tagging','longaxis'),0); + strainiconcell{1,end+1} = myicon('clearalled',gHnd.permanenticonholder,gIcn.clearalled,'Clear all segmentation except in ED',@() callbackfunctions('segmentclearallbutdiastole_Callback'),0); + strainiconcell{1,end+1} = myicon('clearendo',gHnd.configiconholder,gIcn.clearendo,'Clear LV endo in selected slices according to mode',@() segmentation('clearslicesthis_Callback',1,0,0,0),0); + strainiconcell{1,end+1} = myicon('clearepi',gHnd.configiconholder,gIcn.clearepi,'Clear LV epi in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,1,0,0),0); + strainiconcell{1,end+1} = myicon('clearrv',gHnd.configiconholder,gIcn.clearrv,'Clear RV Endo in selected slices according to mode',@() segmentation('clearslicesthis_Callback',0,0,1,0),0); + strainiconcell{1,end+1} = myicon('clearstrain',gHnd.configiconholder,gIcn.clearstrain,'Clear Strain in selected image stack',@() straintagging.straintagging('clearstrain_Callback'),0); + strainiconcell{1,end+1} = myicon('clearstrainall',gHnd.configiconholder,gIcn.clearstrainall,'Clear Strain in all image stacks',@() straintagging.straintagging('clearstrainall_Callback'),0); + g.Icons.strainiconcell = strainiconcell; %Analysis - analysisiconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - analysisiconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour',@() updatetool('move')); - analysisiconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - analysisiconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - analysisiconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - analysisiconcell{1,end+1}=myicon('perfusionstack',g.Handles.configiconholder,g.Icons.config.perfusionstack,'Go to perfusion stacks',@() segment('viewspecial_Callback','perfusion'),0); - analysisiconcell{1,end+1}=myicon('importfromother',g.Handles.configiconholder,g.Icons.config.importfromother,'Import LV segmentation from other image stack with snap',@() segmentation('importsegmentationwithsnap_Callback'),0); - analysisiconcell{1,end+1}=myicon('measure',g.Handles.configiconholder,g.Icons.config.measure,'Place Measurement',@() updatetool('measure')); - analysisiconcell{1,end+1}=myicon('point',g.Handles.configiconholder,g.Icons.config.point,'Place Annotation point',@() updatetool('point')); - analysisiconcell{1,end+1}=myicon('roipen',g.Handles.configiconholder,g.Icons.config.roipen,'ROI pen',@() updatetool('drawroi')); - analysisiconcell{1,end+1}=myicon('addroiinlv',g.Handles.configiconholder,g.Icons.config.addroiinlv,'Add ROIs to sector of LV wall in selected slices',@() roi('roiaddinsector_Callback'),0); - analysisiconcell{1,end+1}=myicon('bullseye',g.Handles.configiconholder,g.Icons.config.bullseye,'Bullseye plot interface',@() reportbullseye,0); - analysisiconcell{1,end+1}=myicon('AVPD',g.Handles.configiconholder,g.Icons.config.AVPD,'AV plane displacement',@() avplane,0); - - analysisiconcell{1,end+1}=myicon('perfusion',g.Handles.configiconholder,g.Icons.config.perfusion, 'Perfusion analysis',@() perfusion.perfusion,0); - analysisiconcell{1,end+1}=myicon('perfusionscoring',g.Handles.configiconholder,g.Icons.config.perfusionscoring, 'Perfusion scoring',@() perfusion.perfusionscoring,0); - analysisiconcell{1,end+1}=myicon('reportperslice',g.Handles.configiconholder,g.Icons.config.reportperslice, 'Report per slice',@() slicereport,0); - analysisiconcell{1,end+1}=myicon('model3d',g.Handles.configiconholder,g.Icons.config.model3d, 'Show 3D model',@() report3dmodel,0); - analysisiconcell{1,end+1}=myicon('hidemeasure',g.Handles.configiconholder,g.Icons.config.hidemeasure,'Hide measurements',@() segment('viewhidemeasures_Callback'),2); - analysisiconcell{1,end+1}=myicon('hidepoint',g.Handles.configiconholder,g.Icons.config.hidepoint,'Hide annotation points',@() segment('viewhidepoints_Callback'),2); - analysisiconcell{1,end+1}= roiflowiconcell{1,end-2};%myicon('hideroi',g.Handles.configiconholder,g.Icons.config.hideroi,'Hide ROI',@() segment('viewhideroi_Callback'),2); - analysisiconcell{1,end+1}=myicon('clearmeasure',g.Handles.configiconholder,g.Icons.config.clearmeasure,'Clear all measurements',@() segment('measureclearall_Callback'),0); - analysisiconcell{1,end+1}=myicon('clearpoint',g.Handles.configiconholder,g.Icons.config.clearpoint,'Clear all annotation points',@() annotationpoint('pointclearall_Callback'),0); - analysisiconcell{1,end+1}=myicon('clearroi',g.Handles.configiconholder,g.Icons.config.clearroi,'Clear selected ROIs',@() roi('roidelete_Callback'),0); - analysisiconcell{1,end+1}=myicon('clearallroi',g.Handles.configiconholder,g.Icons.config.clearallroi,'Clear all ROIs',@() roi('roiclearall_Callback'),0); - g.Icons.analysisiconcell=analysisiconcell; + analysisiconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + analysisiconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + analysisiconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + analysisiconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + analysisiconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + analysisiconcell{1,end+1} = myicon('perfusionstack',gHnd.configiconholder,gIcn.perfusionstack,'Go to perfusion stacks',@() segment('viewspecial_Callback','perfusion'),0); + analysisiconcell{1,end+1} = lviconcell{1,7}; + + analysisiconcell{1,end+1} = myicon('importfromother',gHnd.configiconholder,gIcn.importfromother,'Import LV segmentation from other image stack with snap',@() segmentation('importsegmentationwithsnap_Callback'),0); + analysisiconcell{1,end+1} = myicon('measure',gHnd.configiconholder,gIcn.measure,'Place measurement',@() buttondownfunctions('updatebuttondowns','Measure')); + analysisiconcell{1,end+1} = myicon('point',gHnd.configiconholder,gIcn.point,'Place annotation point',@() buttondownfunctions('updatebuttondowns','Point')); + analysisiconcell{1,end+1} = myicon('roipen',gHnd.configiconholder,gIcn.roipen,'ROI pen',@() buttondownfunctions('updatebuttondowns','Roi')); + analysisiconcell{1,end+1} = myicon('addroiinlv',gHnd.configiconholder,gIcn.addroiinlv,'Add ROIs to sector of LV wall in selected slices',@() roi('roiaddinsector_Callback'),0); + analysisiconcell{1,end+1} = myicon('bullseye',gHnd.configiconholder,gIcn.bullseye,'Bullseye analysis [Ctrl-B]',@() reportbullseye,0); + analysisiconcell{1,end+1} = myicon('AVPD',gHnd.configiconholder,gIcn.AVPD,'AV plane displacement',@() avplane,0); + + analysisiconcell{1,end+1} = myicon('perfusion',gHnd.configiconholder,gIcn.perfusion, 'Perfusion analysis',@() perfusion.perfusion,0); + analysisiconcell{1,end+1} = myicon('perfusionscoring',gHnd.configiconholder,gIcn.perfusionscoring, 'Perfusion scoring',@() perfusion.perfusionscoring,0); + analysisiconcell{1,end+1} = myicon('reportperslice',gHnd.configiconholder,gIcn.reportperslice, 'Report per slice',@() slicereport,0); + analysisiconcell{1,end+1} = myicon('model3d',gHnd.configiconholder,gIcn.model3d, 'Show 3D model',@() report3dmodel,0); + analysisiconcell{1,end+1} = myicon('hidemeasure',gHnd.configiconholder,gIcn.hidemeasure,'Hide measurements',@() viewfunctions('hide_Callback'),2); + analysisiconcell{1,end+1} = myicon('hidepoint',gHnd.configiconholder,gIcn.hidepoint,'Hide annotation points',@() viewfunctions('hide_Callback'),2); + analysisiconcell{1,end+1}= roiflowiconcell{1,end-2};%myicon('hideroi',gHnd.configiconholder,gIcn.hideroi,'Hide ROI',@() segment('viewhideroi_Callback'),2); + analysisiconcell{1,end+1} = myicon('clearmeasure',gHnd.configiconholder,gIcn.clearmeasure,'Clear all measurements',@() callbackfunctions('measureclearall_Callback'),0); + analysisiconcell{1,end+1} = myicon('clearpoint',gHnd.configiconholder,gIcn.clearpoint,'Clear all annotation points',@() callbackfunctions('pointclearall_Callback'),0); + analysisiconcell{1,end+1} = myicon('clearroi',gHnd.configiconholder,gIcn.clearroi,'Clear selected ROIs',@() roi('roidelete_Callback'),0); + analysisiconcell{1,end+1} = myicon('clearallroi',gHnd.configiconholder,gIcn.clearallroi,'Clear all ROIs',@() roi('roiclearall_Callback'),0); + g.Icons.analysisiconcell = analysisiconcell; %Image - imageiconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - imageiconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour',@() updatetool('move')); - imageiconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - imageiconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - imageiconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - imageiconcell{1,end+1}=myicon('resetlight',g.Handles.configiconholder,g.Icons.config.resetlight,'Reset contrast and brightness',@() segment('resetlight_Callback'),0); - imageiconcell{1,end+1}=myicon('autocontrastall',g.Handles.configiconholder,g.Icons.config.autocontrastall,'Set contrast and brightness to predefined values for all images',@() segment('autocontrastall_Callback'),0); - imageiconcell{1,end+1}=myicon('resetlightall',g.Handles.configiconholder,g.Icons.config.resetlightall,'Reset contrast and brightness for all imagestacks',@() segment('resetlightall_Callback'),0); - imageiconcell{1,end+1}=myicon('crop',g.Handles.configiconholder,g.Icons.config.crop,'Manual crop',@() updatetool('crop')); - imageiconcell{1,end+1}=myicon('cropall',g.Handles.configiconholder,g.Icons.config.cropall,'Auto crop all',@() updatetool('autocropall'),0); - imageiconcell{1,end+1}=myicon('croplv',g.Handles.configiconholder,g.Icons.config.croplv,'LV crop',@() lvsegmentation('croplvall',0),0); - imageiconcell{1,end+1}=myicon('cineplay',g.Handles.configiconholder,g.Icons.config.cineplay,'Open cine tool',@() segment('cinetool_Callback'),2); - imageiconcell{1,end+1}=myicon('movie',g.Handles.configiconholder,g.Icons.config.movie,'Open movie tool',@() export('exportmovierecorder_Callback'),0); - imageiconcell{1,end+1}=myicon('click3d',g.Handles.configiconholder,g.Icons.config.click3d,'Set 3D point',@() updatetool('click3d')); - imageiconcell{1,end+1}=myicon('rotate90',g.Handles.configiconholder,g.Icons.config.rotate90,'Rotate 90 degrees clockwise',@() tools('rotate90right_Callback'),0); - imageiconcell{1,end+1}=myicon('mpr',g.Handles.configiconholder,g.Icons.config.mpr,'Reconstruct image stack',@() reformater,0); - imageiconcell{1,end+1}=myicon('mergestacks',g.Handles.configiconholder,g.Icons.config.mergestacks,'Merge stacks',@() mergestacks,0); - imageiconcell{1,end+1}=myicon('imageinfo',g.Handles.configiconholder,g.Icons.config.imageinfo,'View and adjust image info',@() tools('imageinfo_Callback'),0); - imageiconcell{1,end+1}=myicon('patientinfo',g.Handles.configiconholder,g.Icons.config.patientinfo,'View and adjust patient info',@() tools('viewpatientinfo_Callback'),0); - imageiconcell{1,end+1}=myicon('hidetext',g.Handles.configiconholder,g.Icons.config.hidetext,'Hide text',@() segment('viewhidetext_Callback'),2); - imageiconcell{1,end+1}=myicon('hideplus',g.Handles.configiconholder,g.Icons.config.hideplus,'Hide center cross',@() segment('viewhideplus_Callback'),2); - imageiconcell{1,end+1}=myicon('hideintersections',g.Handles.configiconholder,g.Icons.config.hideintersections,'Hide intersection lines',@() segment('viewhideinterp_Callback'),2); - imageiconcell{1,end+1}=myicon('hideothercontour',g.Handles.configiconholder,g.Icons.config.hideothercontour,'Hide other contour points',@() segment('viewhideothercontour_Callback'),2); - g.Icons.imageiconcell=imageiconcell; + imageiconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + imageiconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + imageiconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + imageiconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + imageiconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + imageiconcell{1,end+1} = myicon('resetlight',gHnd.configiconholder,gIcn.resetlight,'Reset contrast and brightness',@() segment('resetlight_Callback'),0); + imageiconcell{1,end+1} = myicon('autocontrastall',gHnd.configiconholder,gIcn.autocontrastall,'Set contrast and brightness to predefined values for all images',@() segment('autocontrastall_Callback'),0); + imageiconcell{1,end+1} = myicon('resetlightall',gHnd.configiconholder,gIcn.resetlightall,'Reset contrast and brightness for all imagestacks',@() segment('resetlightall_Callback'),0); + imageiconcell{1,end+1} = lviconcell{1,7}; + + imageiconcell{1,end+1} = myicon('crop',gHnd.configiconholder,gIcn.crop,'Manual crop',@() buttondownfunctions('updatebuttondowns','crop')); + imageiconcell{1,end+1} = myicon('cropall',gHnd.configiconholder,gIcn.cropall,'Auto crop all',@() autocropallgui('init'),0); + imageiconcell{1,end+1} = myicon('croplv',gHnd.configiconholder,gIcn.croplv,'LV crop',@() lvsegmentation('croplvall',0),0); + imageiconcell{1,end+1} = myicon('cineplay',gHnd.configiconholder,gIcn.cineplay,'Open cine tool',@() segment('cinetool_Callback'),2); + imageiconcell{1,end+1} = myicon('movie',gHnd.configiconholder,gIcn.movie,'Open movie tool',@() export('exportmovierecorder_Callback'),0); + imageiconcell{1,end+1} = myicon('click3d',gHnd.configiconholder,gIcn.click3d,'Set 3D point',@() buttondownfunctions('updatebuttondowns','click3d')); + imageiconcell{1,end+1} = myicon('rotate90',gHnd.configiconholder,gIcn.rotate90,'Rotate 90 degrees clockwise',@() tools('rotate90right_Callback'),0); + imageiconcell{1,end+1} = myicon('mpr',gHnd.configiconholder,gIcn.mpr,'Reconstruct image stack',@() reformater,0); + imageiconcell{1,end+1} = myicon('mergestacks',gHnd.configiconholder,gIcn.mergestacks,'Merge stacks',@() mergestacks,0); + imageiconcell{1,end+1} = myicon('imageinfo',gHnd.configiconholder,gIcn.imageinfo,'View and adjust image info',@() tools('imageinfo_Callback'),0); + imageiconcell{1,end+1} = myicon('patientinfo',gHnd.configiconholder,gIcn.patientinfo,'View and adjust patient info',@() tools('viewpatientinfo_Callback'),0); + imageiconcell{1,end+1}=roiflowiconcell{1,end-2};%myicon('hidetext',gHnd.configiconholder,gIcn.hidetext,'Hide text',@() viewfunctions('hide_Callback'),2); + imageiconcell{1,end+1} = myicon('hideplus',gHnd.configiconholder,gIcn.hideplus,'Hide center cross',@() viewfunctions('hide_Callback'),2); + imageiconcell{1,end+1} = myicon('hideintersections',gHnd.configiconholder,gIcn.hideintersections,'Hide intersection lines',@() viewfunctions('hide_Callback'),2); + imageiconcell{1,end+1} = myicon('hideothercontour',gHnd.configiconholder,gIcn.hideothercontour,'Hide other contour points',@() viewfunctions('hide_Callback'),2); + g.Icons.imageiconcell = imageiconcell; %TXmap - txmapiconcell{1,1}=myicon('select',g.Handles.configiconholder,g.Icons.config.select,'Select image stack or object',@() updatetool('select')); - txmapiconcell{1,end+1}=myicon('move',g.Handles.configiconholder,g.Icons.config.move,'Translate contour',@() updatetool('move')); - txmapiconcell{1,end+1}=myicon('scale',g.Handles.configiconholder,g.Icons.config.scale,'Scale object',@() updatetool('scale')); - txmapiconcell{1,end+1}=myicon('contrastbrightness',g.Handles.configiconholder,g.Icons.config.contrastbrightness,'Manually change contrast and brightness',@() updatetool('contrast')); - txmapiconcell{1,end+1}=myicon('autocontrast',g.Handles.configiconholder,g.Icons.config.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); - txmapiconcell{1,end+1}=myicon('resetlight',g.Handles.configiconholder,g.Icons.config.resetlight,'Reset contrast and brightness',@() segment('resetlight_Callback'),0); - txmapiconcell{1,end+1}=myicon('importfromother',g.Handles.configiconholder,g.Icons.config.importfromother,'Import LV segmentation from cine to Tx map image stack',@() segmentation('importfromcine2txmap_Callback'),0); - txmapiconcell{1,end+1}=myicon('roipen',g.Handles.configiconholder,g.Icons.config.roipen,'ROI pen',@() updatetool('drawroi')); - txmapiconcell{1,end+1}=myicon('addroiinlv',g.Handles.configiconholder,g.Icons.config.addroiinlv,'Add ROIs to sector of LV wall in selected slices',@() roi('roiaddinsector_Callback'),0); - txmapiconcell{1,end+1}=myicon('T1',g.Handles.configiconholder,g.Icons.config.T1, 'T1 analysis',@() txmap('init',1),0); - txmapiconcell{1,end+1}=myicon('T2',g.Handles.configiconholder,g.Icons.config.T2, 'T2 analysis',@() txmap('init',2),0); - txmapiconcell{1,end+1}=myicon('T2star',g.Handles.configiconholder,g.Icons.config.T2star, 'T2* analysis',@() t2star.t2star,0); - txmapiconcell{1,end+1}=myicon('ecv',g.Handles.configiconholder,g.Icons.config.ecv, 'ECV analysis',@() ecv('init_Callback'),0); - txmapiconcell{1,end+1}=myicon('T1precolormap',g.Handles.configiconholder,g.Icons.config.T1precolormap, 'T1 pre colormap',@() tools('setcolormap_Callback','t1pre'),0); - txmapiconcell{1,end+1}=myicon('T1postcolormap',g.Handles.configiconholder,g.Icons.config.T1postcolormap, 'T1 post colormap',@() tools('setcolormap_Callback','t1post'),0); - txmapiconcell{1,end+1}=myicon('T2colormap',g.Handles.configiconholder,g.Icons.config.T2colormap, 'T2 colormap',@() tools('setcolormap_Callback','t2'),0); - txmapiconcell{1,end+1}=myicon('T2starcolormap',g.Handles.configiconholder,g.Icons.config.T2starcolormap, 'T2* colormap',@() tools('setcolormap_Callback','t2star'),0); - txmapiconcell{1,end+1}=myicon('ecvcolormap',g.Handles.configiconholder,g.Icons.config.ecvcolormap, 'ECV colormap',@() tools('setcolormap_Callback','ecv'),0); - txmapiconcell{1,end+1}=myicon('greycolormap',g.Handles.configiconholder,g.Icons.config.greycolormap, 'Grey colormap',@() tools('setcolormap_Callback','gray'),0); + txmapiconcell{1,1} = myicon('select',gHnd.configiconholder,gIcn.select,'Select image stack or object',@() buttondownfunctions('updatebuttondowns','select')); + txmapiconcell{1,end+1} = myicon('move',gHnd.configiconholder,gIcn.move,'Translate contour',@() buttondownfunctions('updatebuttondowns','move')); + txmapiconcell{1,end+1} = myicon('scale',gHnd.configiconholder,gIcn.scale,'Scale object',@() buttondownfunctions('updatebuttondowns','scale')); + txmapiconcell{1,end+1} = myicon('contrastbrightness',gHnd.configiconholder,gIcn.contrastbrightness,'Manually change contrast and brightness',@() buttondownfunctions('updatebuttondowns','Contrast')); + txmapiconcell{1,end+1} = myicon('autocontrast',gHnd.configiconholder,gIcn.autocontrast,'Set contrast and brightness to predefined values',@() segment('autocontrast_Callback'),0); + txmapiconcell{1,end+1} = myicon('resetlight',gHnd.configiconholder,gIcn.resetlight,'Reset contrast and brightness',@() segment('resetlight_Callback'),0); + txmapiconcell{1,end+1} = lviconcell{1,7}; + + txmapiconcell{1,end+1} = myicon('importfromother',gHnd.configiconholder,gIcn.importfromother,'Import LV segmentation from cine to Tx map image stack',@() segmentation('importfromcine2txmap_Callback'),0); + txmapiconcell{1,end+1} = myicon('roipen',gHnd.configiconholder,gIcn.roipen,'ROI pen',@() buttondownfunctions('updatebuttondowns','Roi')); + txmapiconcell{1,end+1} = myicon('addroiinlv',gHnd.configiconholder,gIcn.addroiinlv,'Add ROIs to sector of LV wall in selected slices',@() roi('roiaddinsector_Callback'),0); + txmapiconcell{1,end+1} = myicon('T1',gHnd.configiconholder,gIcn.T1, 'T1 analysis',@() txmap('init',1),0); + txmapiconcell{1,end+1} = myicon('T2',gHnd.configiconholder,gIcn.T2, 'T2 analysis',@() txmap('init',2),0); + txmapiconcell{1,end+1} = myicon('T2star',gHnd.configiconholder,gIcn.T2star, 'T2* analysis',@() t2star.t2star,0); + txmapiconcell{1,end+1} = myicon('ecv',gHnd.configiconholder,gIcn.ecv, 'ECV analysis',@() ecv('init_Callback'),0); + txmapiconcell{1,end+1} = myicon('T1precolormap',gHnd.configiconholder,gIcn.T1precolormap, 'T1 pre colormap',@() tools('setcolormap_Callback','t1pre'),0); + txmapiconcell{1,end+1} = myicon('T1postcolormap',gHnd.configiconholder,gIcn.T1postcolormap, 'T1 post colormap',@() tools('setcolormap_Callback','t1post'),0); + txmapiconcell{1,end+1} = myicon('T2colormap',gHnd.configiconholder,gIcn.T2colormap, 'T2 colormap',@() tools('setcolormap_Callback','t2'),0); + txmapiconcell{1,end+1} = myicon('T2starcolormap',gHnd.configiconholder,gIcn.T2starcolormap, 'T2* colormap',@() tools('setcolormap_Callback','t2star'),0); + txmapiconcell{1,end+1} = myicon('ecvcolormap',gHnd.configiconholder,gIcn.ecvcolormap, 'ECV colormap',@() tools('setcolormap_Callback','ecv'),0); + txmapiconcell{1,end+1} = myicon('greycolormap',gHnd.configiconholder,gIcn.greycolormap, 'Grey colormap',@() tools('setcolormap_Callback','gray'),0); txmapiconcell{1,end+1}= roiflowiconcell{1,end-2}; - txmapiconcell{1,end+1}=myicon('clearroi',g.Handles.configiconholder,g.Icons.config.clearroi,'Clear selected ROIs',@() roi('roidelete_Callback'),0); - txmapiconcell{1,end+1}=myicon('clearallroi',g.Handles.configiconholder,g.Icons.config.clearallroi,'Clear all ROIs',@() roi('roiclearall_Callback'),0); + txmapiconcell{1,end+1} = myicon('clearroi',gHnd.configiconholder,gIcn.clearroi,'Clear selected ROIs',@() roi('roidelete_Callback'),0); + txmapiconcell{1,end+1} = myicon('clearallroi',gHnd.configiconholder,gIcn.clearallroi,'Clear all ROIs',@() roi('roiclearall_Callback'),0); g.Icons.txmapiconcell = txmapiconcell; end @@ -318,341 +368,34 @@ function initconfigplaceholder(varargin) function initribbonplaceholder(varargin) %-------------------------------------- - g=varargin{1}; - %initiate iconholder for toggle axes - iconCell=cell(1,7); - iconCell{1}=myicon('ribbonlv',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbonlvoff,... - 'LV', @() segment('togglebuttonLV_Callback'),1,1,g.Icons.toggleicons.ribbonlvon); - iconCell{2}=myicon('ribbonrv',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbonrvoff,... - 'RV',@() segment('togglebuttonRV_Callback'),1,1,g.Icons.toggleicons.ribbonrvon); - iconCell{3}=myicon('ribbonflow',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbonflowoff,... - 'ROI/FLOW',@() segment('togglebuttonROIFLOW_Callback'),1,1,g.Icons.toggleicons.ribbonflowon); - iconCell{4}=myicon('ribbonviability',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbonviabilityoff,... - 'Viability',@() segment('togglebuttonVia_Callback'),1,1,g.Icons.toggleicons.ribbonviabilityon); - iconCell{5}=myicon('ribbontxmap',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbontxmapoff,... - 'TX maps and ECV',@() segment('togglebuttontxmap_Callback'),1,1,g.Icons.toggleicons.ribbontxmapon); - iconCell{6}=myicon('ribbonanalysis',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbonanalysisoff,... - 'Analysis',@() segment('togglebuttonAnalysis_Callback'),1,1,g.Icons.toggleicons.ribbonanalysison); - iconCell{7}=myicon('ribbonimage',g.Handles.toggleiconholder,g.Icons.toggleicons.ribbonimageoff,... - 'Image',@() segment('togglebuttonImage_Callback'),1,1,g.Icons.toggleicons.ribbonimageon); -% - g.Handles.toggleiconholder.add(iconCell); - pos=plotboxpos(g.Handles.toggleiconholder.axeshandle); - currentpos=get(g.Handles.toggleiconholder.axeshandle,'position'); - set(g.Handles.toggleiconholder.axeshandle,'position',currentpos-[pos(1),0,0,0]); - end - - %-------------------------- - function initmaintoolbar(g) - %-------------------------- - %Intialization of main toolbar - %If new handles are added, add those to list in killhandles.m as well! - - %Create - g.Handles.maintoolbar = uitoolbar(g.imagefig); - set(g.fig,'color',g.GUISettings.BackgroundColor); %Added EH: - - %fileopen - g.addmainicon_helper('segment(''fileopen_Callback'')', ... - 'Open images',... - g.Icons.opendoc,... - 'fileopenicon'); - - %filesave - g.addmainicon_helper('segment(''filesaveallas_Callback'')',... - 'Save All Image Stacks and Segmentation to Disc',... - g.Icons.save,... - 'filesaveicon'); - - %database - g.addmainicon_helper('patientdatabase',... - 'Open Segment Patient Database',... - g.Icons.database,... - 'databaseicon','on'); - - %database add patient to - g.addmainicon_helper('filemenu(''savetopatientdatabase_Callback'')',... - 'Save Image Stacks and Segmentation to Patient Database',... - g.Icons.databaseadd,... - 'databaseaddicon'); - - %pacs - g.addmainicon_helper('pacs(''init_Callback'')',... - 'Retrieve Images from PACS',... - g.Icons.connect,... - 'pacsicon','on'); - - %pacs add to - g.addmainicon_helper('filemenu(''savetopacs_Callback'')',... - 'Save Image Stacks and Segmentation to PACS',... - g.Icons.connectadd,... - 'pacsaddicon'); - - %import from CD - g.addmainicon_helper('utility(''utilitycopyandsortfromcd_Callback'')',... - 'Import Files from CD',... - g.Icons.importfromcd,... - 'importfromcdicon'); - - %View 1 panel - g.addmainicon_helper('drawfunctions(''drawall'',1)',... - 'View one image panel',... - g.Icons.panel1,... - 'view1panelicon',... - 'on'); - - %View 2 panel - g.addmainicon_helper('drawfunctions(''drawall'',1,2)',... - 'View two image panels',... - g.Icons.panel2,... - 'view2panelicon'); - - %View 2x1 panel - g.addmainicon_helper('drawfunctions(''drawall'',2,1)',... - 'View two image panels',... - g.Icons.panel2x1,... - 'view2x1panelicon'); - - %View three*1 panel - g.addmainicon_helper('drawfunctions(''drawall'',3,1)',... - 'View three image panels',... - g.Icons.panel3,... - 'view3panelicon'); - - %View 1*three panel - g.addmainicon_helper('drawfunctions(''drawall'',1,3)',... - 'View three image panels',... - g.Icons.panel1x3,... - 'view1x3panelicon'); - - %View four panel - g.addmainicon_helper('drawfunctions(''drawall'',4)',... - 'View four image panels',... - g.Icons.panel4,... - 'view4panelicon'); - - %View six panel - g.addmainicon_helper('drawfunctions(''drawall'',6)',... - 'View six image panels',... - g.Icons.panel6,... - 'view6panelicon'); - - %View 9 panel - g.addmainicon_helper('drawfunctions(''drawall'',9)',... - 'View nine image panels',... - g.Icons.panel9,... - 'view9panelicon'); - - %Open view loader - g.addmainicon_helper('segmentview',... - 'Launch GUI for saving custom views',... - g.Icons.saveview,... - 'saveviewicon'); - - %Show/hide pins - g.addmainicon_helper('segment(''viewhidepins_Callback'')',... - 'Hide/show pins',... - g.Icons.hidepins,... - 'hidepinsicon',... - 'on'); - - %Show/hide contour from other image stacks. - g.addmainicon_helper('segment(''viewhideothercontour_Callback'')',... - 'Hide/show LV/RV contour from other image stacks',... - g.Icons.hideothercontour,... - 'hideothercontouricon',... - 'off'); - - %Show/hide interpolation points - g.addmainicon_helper('segment(''viewhideinterp_Callback'')',... - 'Hide/show interpolation points',... - g.Icons.hideinterp,... - 'hideinterpicon',... - 'off'); - - %Show/hide lv segmentation - g.addmainicon_helper('segment(''viewhidelv_Callback'')',... - 'Hide/show left ventricle segmentation',... - g.Icons.hidelv,... - 'hidelvicon',... - 'off'); - - %Show/hide rv segmentation - g.addmainicon_helper('segment(''viewhiderv_Callback'')',... - 'Hide/show right ventricle segmentation',... - g.Icons.hiderv,... - 'hidervicon',... - 'off'); - - %Show/hide scar - g.addmainicon_helper('segment(''viewhidescar_Callback'')',... - 'Hide/show scar',... - g.Icons.hidescar,... - 'hidescaricon',... - 'off'); - - %Show/hide mar - g.addmainicon_helper('segment(''viewhidemar_Callback'')',... - 'Hide/show MaR',... - g.Icons.hidemar,... - 'hidemaricon',... - 'off'); - - %Show/hide roi - g.addmainicon_helper('segment(''viewhideroi_Callback'')',... - 'Hide/show roi''s',... - g.Icons.hideroi,... - 'hideroiicon',... - 'off'); - - %Show/hide measures - g.addmainicon_helper('segment(''viewhidemeasures_Callback'')',... - 'Hide/show measurements',... - g.Icons.hidemeasure,... - 'hidemeasuresicon',... - 'off'); - - %Show/hide annotation points - g.addmainicon_helper('segment(''viewhidepoints_Callback'')',... - 'Hide/show annotation points',... - g.Icons.hidepoint,... - 'hidepointsicon',... - 'off'); - - %Show/hide plus/center point - g.addmainicon_helper('segment(''viewhideplus_Callback'')',... - 'Hide/show image center point',... - g.Icons.hideplus,... - 'hideplusicon',... - 'off'); - - %Show/hide intersections - g.addmainicon_helper('segment(''viewhideintersections_Callback'')',... - 'Hide/show image plane intersections',... - g.Icons.hideintersections,... - 'hideintersectionsicon',... - 'off'); - - %Show/hide text - g.addmainicon_helper('segment(''viewhidetext_Callback'')',... - 'Hide/show text',... - g.Icons.hidetext,... - 'hidetexticon',... - 'off'); - - if isequal(g.GUISettings.PapilarColor,1) - g.addmainicon_helper('segment(''viewhidepap_Callback'')',... - 'Hide/show papillary overlay',... - g.Icons.hidepapwhite,... - 'hidepapicon','off'); - else - g.addmainicon_helper('segment(''viewhidepap_Callback'')',... - 'Hide/show papillary overlay',... - g.Icons.hidepapblack,... - 'hidepapicon','off'); - end - %show/hide manual interaction overlay - g.addmainicon_helper('segment(''viewhidemanualinteraction_Callback'')',... - 'Hide/show manual interaction for Scar/MaR',... - g.Icons.hideoverlaynew,... - 'hideoverlayicon','off'); - - %Show colorbar - g.addmainicon_helper('segment(''viewhidecolorbar_Callback'')',... - 'Show colorbar in current image stack',... - g.Icons.colorbar,... - 'colorbaricon',... - 'off'); - - %View pixely/interpolated - g.addmainicon_helper('segment(''viewinterp_Callback'')',... - 'View image pixels',... - g.Icons.viewpixely,... - 'viewpixelyicon',... - 'off'); - - %Help icon - props.ClickedCallback = 'segmenthelp(''about_Callback'')'; - props.ToolTip = 'About'; - props.CData = g.Icons.help; - props.Tag = 'about'; - props.separator = 'on'; - g.Handles.abouticon = uitoggletool(g.Handles.maintoolbar,props); - end - - - %-------------------------- - function measurementinit(g) - %-------------------------- - %init objects for measurement panel in AxesTables - -% set(g.Handles.lvuipanel,'BackgroundColor','black'); -% set(g.Handles.flowuipanel,'BackgroundColor','black'); -% set(g.Handles.reportpanel,'BackgroundColor','black'); -% set(g.Handles.barpanel,'BackgroundColor','black'); - - bl = '---'; %no values on Init - bl2 = {bl,bl}; - - g.AxesTables.volume = axestable(g.Handles.volumeresultaxes); - g.AxesTables.flow = axestable(g.Handles.flowresultaxes); - g.AxesTables.measurement = axestable(g.Handles.measurementresultaxes); - - m=g.getmeasurementstruct(); - - %LV and RV report table - g.AxesTables.volume.backgroundcolor = [0.94 0.94 0.94]; %[0 0 0];% - g.AxesTables.volume.fontcolor = [0 0 0]; % [1 1 1];% - g.AxesTables.volume.fontsize = 10; - g.AxesTables.volume.ystep = 15; -% g.AxesTables.volume.FigWith = 300; - g.AxesTables.volume.addTable('LV',2,1,[0.6 0.4]); - g.AxesTables.volume.addKey('LVM','ED/ES LVM','g',bl); - g.AxesTables.volume.addKey('LVEDV','EDV','ml',bl); - g.AxesTables.volume.addKey('LVESV','ESV','ml',bl); - g.AxesTables.volume.addKey('LVSV','SV','ml',bl); - g.AxesTables.volume.addKey('LVEF','EF','%',bl); - g.AxesTables.volume.addKey('LVCO','CO','l/min',bl); - g.AxesTables.volume.addKey('LVHR','HR','bpm',bl); - %g.AxesTables.volume.addKey('INFO','','',''); - -% g.AxesTables.volume.addSpace(); - g.AxesTables.volume.addTable('RV',2,1,[0.6 0.4]); - g.AxesTables.volume.addKey('RVM','ED/ES RVM','g',bl); - g.AxesTables.volume.addKey('RVEDV','EDV','ml',bl); - g.AxesTables.volume.addKey('RVESV','ESV','ml',bl); - g.AxesTables.volume.addKey('RVSV','SV','ml',bl); - g.AxesTables.volume.addKey('RVEF','EF','%',bl); -% g.AxesTables.volume.addKey('RVCO','CO','l/min',bl); -% g.AxesTables.volume.addKey('RVHR','HR','bpm',bl); - - %Flow report table - g.AxesTables.flow.backgroundcolor = [0.94 0.94 0.94]; %[0 0 0];% - g.AxesTables.flow.fontcolor = [0 0 0]; %[1 1 1];% - g.AxesTables.flow.ystep = 20;%16; - g.AxesTables.flow.fontsize = 10; - g.AxesTables.flow.addTable('Flow',2,1,[0.65 0.35]); - g.AxesTables.flow.addKey('ROI','ROI','',''); - g.AxesTables.flow.addKey('Netvol','Net vol','ml',bl); - %g.AxesTables.flow.addKey('Forward','Forward','ml',bl); - g.AxesTables.flow.addKey('Backward','Backward','ml',bl); - g.AxesTables.flow.addKey('Regfrac','Regurg. frac.','%',bl); - g.AxesTables.flow.addKey('FlowCO','FlowCO','l/min',bl); - g.AxesTables.flow.addKey('FlowHR','HR','bpm',bl); + g = varargin{1}; + gHndtoggle = g.Handles.toggleiconholder; + gIcntoggle = g.Icons.toggleicons; + %initiate iconholder for toggle axes + iconCell = cell(1,7); + iconCell{1} = myicon('ribbonlv',gHndtoggle,gIcntoggle.ribbonlvoff,... + 'LV', @() g.togglebuttonLV_Callback,1,1,gIcntoggle.ribbonlvon); + iconCell{2} = myicon('ribbonrv',gHndtoggle,gIcntoggle.ribbonrvoff,... + 'RV',@() g.togglebuttonRV_Callback,1,1,gIcntoggle.ribbonrvon); + iconCell{3} = myicon('ribbonflow',gHndtoggle,gIcntoggle.ribbonflowoff,... + 'ROI/FLOW',@() g.togglebuttonROIFLOW_Callback,1,1,gIcntoggle.ribbonflowon); + iconCell{4} = myicon('ribbonviability',gHndtoggle,gIcntoggle.ribbonviabilityoff,... + 'Viability',@() g.togglebuttonVia_Callback,1,1,gIcntoggle.ribbonviabilityon); + iconCell{5} = myicon('ribbontxmap',gHndtoggle,gIcntoggle.ribbontxmapoff,... + 'TX maps and ECV',@() g.togglebuttontxmap_Callback,1,1,gIcntoggle.ribbontxmapon); + iconCell{6} = myicon('ribbonstrain',gHndtoggle,gIcntoggle.ribbonstrainoff,... + 'Strain',@() g.togglebuttonStrain_Callback,1,1,gIcntoggle.ribbonstrainon); + iconCell{7} = myicon('ribbonanalysis',gHndtoggle,gIcntoggle.ribbonanalysisoff,... + 'Analysis',@() g.togglebuttonAnalysis_Callback,1,1,gIcntoggle.ribbonanalysison); + iconCell{8} = myicon('ribbonimage',gHndtoggle,gIcntoggle.ribbonimageoff,... + 'Image',@() g.togglebuttonImage_Callback,1,1,gIcntoggle.ribbonimageon); - %measurement report table - g.AxesTables.measurement.backgroundcolor = [0.94 0.94 0.94]; %[0 0 0];% - g.AxesTables.measurement.fontcolor = [0 0 0]; %[1 1 1];% - g.AxesTables.measurement.ystep = 20;%16; - g.AxesTables.measurement.fontsize = 10; - g.AxesTables.measurement.addTable('Measurement',2,1,[0.6 0.4]); - g.AxesTables.measurement.addKey('m1',bl,'',bl); - g.AxesTables.measurement.addKey('m2',bl,'',bl); - g.AxesTables.measurement.addKey('m3',bl,'',bl); - g.AxesTables.measurement.addKey('m4',bl,'',bl); + gHndtoggle.add(iconCell); + pos = plotboxpos(gHndtoggle.axeshandle); + currentpos = get(gHndtoggle.axeshandle,'position'); + set(gHndtoggle.axeshandle,'position',currentpos-[pos(1),0,0,0]); + end - end - %---------------------- function inittoolbar(g) %---------------------- @@ -662,347 +405,183 @@ function inittoolbar(g) g.GUISettings.BottomGapHeight = 0.133; g.GUISettings.RightGapWidth = 0.21; g.GUISettings.ShowColorbar = false; - - %Initiate AxesTables objects - g.measurementinit; - - %Clear all measurements - g.updateaxestables('flowclearall'); - g.updateaxestables('volumeclearall'); - - %initateplugins + + %--- Initialize all menu items segment('initmenu'); - if isequal(36,getmodule(35,'KI',[],true)); - uimenu(g.Handles.analysismenu,'Label','RAMP', ... - 'Callback','plugin_RAMP(''init'')'); - end - end - - - %--------------------------------- - function m=getmeasurementstruct(g) - %--------------------------------- - %Set up the structure of the result tables in main interface - %For now mostly copied from RVQ - - %category type code shortname longname showinpanel showinreport - %LV mm ASW Asw Anterior Septal Wall Thickness 1 - - if isempty([]) %Replace property CVQMeasurements - try - all=textread('SegmentMeasurements.txt','%s','delimiter',';'); - catch - myfailed('Could not read SegmentMeasurements.txt file.'); - return; - end; - - write_pos=1; - read_pos=1; - m=cell(1,1); - - while read_pos0 - g.FlowNO = NO; - g.FlowROI = SET(NO).RoiCurrent; %RoiN; - elseif ~isempty(SET) && ~isempty(SET(NO).Flow) && ~isempty(SET(SET(NO).Flow.MagnitudeNo).Flow) && SET(SET(NO).Flow.MagnitudeNo).RoiN>0 - g.FlowNO = SET(NO).Flow.MagnitudeNo; - g.FlowROI = SET(SET(NO).Flow.MagnitudeNo).RoiCurrent; %RoiN; - else - g.FlowNO = []; - g.FlowROI = []; - if strcmp(arg,'area') - return; + global SET NO + %for segment we always use the values in the NO + no = NO; + + c = cell(1,8); + if ~isempty(SET) && ~isempty(NO) + lvmEDT = SET(no).LVM(SET(no).EDT)*1.05; + lvmEST = SET(no).LVM(SET(no).EST)*1.05; + edv = SET(no).EDV; + esv = SET(no).ESV; + sv = SET(no).SV; + co = (SET(no).HeartRate*SET(no).SV)/100; + if lvmEDT > 0 && lvmEDT < 1 + %convert to milligram + lvmEDT = 1000*lvmEDT; + lvmEST = 1000*lvmEST; + g.Handles.lvheadertext.String{1} = 'ED/ES LVM (mg)'; + else + g.Handles.lvheadertext.String{1} = 'ED/ES LVM (g)'; end + + if edv > 0 && edv < 1 + %convert to mikroliters + edv = 1000*edv; + g.Handles.lvheadertext.String{2} = ['EDV (',char(181),'l)']; + esv = 1000*esv; + g.Handles.lvheadertext.String{3} = ['ESV (',char(181),'l)']; + sv = 1000*sv; + g.Handles.lvheadertext.String{4} = ['SV (',char(181),'l)']; + co = 1000*co; + g.Handles.lvheadertext.String{6} = 'CO (ml/min)'; + else + g.Handles.lvheadertext.String{2} = 'EDV (ml)'; + g.Handles.lvheadertext.String{3} = 'ESV (ml)'; + g.Handles.lvheadertext.String{4} = 'SV (ml)'; + g.Handles.lvheadertext.String{6} = 'CO (l/min)'; + end + + c{1} = round(lvmEDT); + c{2} = round(lvmEST); + c{3} = round(edv); + c{4} = round(esv); + c{5} = round(sv); + c{6} = round(100*SET(no).EF); + c{7} = round(co)/10; + c{8} = round(SET(no).HeartRate); end - switch arg - case 'volume' - g.updatevolumeaxes; - g.volumereportupdate(varargin{:}); - case 'volumeclearall' - g.updatevolumeaxes; - g.volumereportupdate(varargin{:}); - case {'area','flow'} - g.updateflowaxes; - g.flowreportupdate; - case {'areaclearall','flowclearall'} - g.updateflowaxes; - g.flowreportupdate; - case {'measure'} - g.measurementreportupdate; - case {'measureclearall'} - g.measurementreportupdate; - case 'allreports' - g.updatevolumeaxes; - g.volumereportupdate(varargin{:}); - g.updateflowaxes; - g.flowreportupdate; - g.measurementreportupdate; - end + c_inds = cellfun(@(x) isempty(x) || isnan(x) || x == 0,c); + [c{c_inds}] = deal('---'); + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.lvreporttext.String = sprintf('%s / %s \n%s \n%s \n%s \n%s \n%s \n%s',c{:}); + %adjust fontsize according to the available space on screen + pos = getpixelposition(g.Handles.lvreporttext); + widthinpixel = pos(3); + cmperwidth = 0.053*widthinpixel/10; + cmperlength = 0.0265*pos(4)/9.5; + g.fontsizeincm = min(cmperwidth,cmperlength); + set(g.Handles.lvreporttext,'FontSize',g.fontsizeincm); + g.Handles.lvheadertext.FontSize = g.fontsizeincm; + end - - %----------------------------- - function volumereportupdate(g) - %----------------------------- - %Update LV and RV report in axestables - global SET DATA - -% m=g.(); - bla = {'---'}; - - % -- LV -- - - s = []; - s.LVM = bla; - s.LVEDV = bla; - s.LVESV = bla; - s.LVSV = bla; - s.LVEF = bla; - s.LVCO = bla; - s.LVHR = bla; - updatestruct = s; - % title{1} = 'LV'; - unitV='ml'; %default volume unit - unitg='g'; - unitcorr=1; %correction for volume unit - - if ~isempty(DATA.LVNO) % isfield(DATA,'LVNO') && - no = DATA.LVNO(1); - haslv = ~isempty(SET(no).EpiX) || ~isempty(SET(no).EndoX); - - if haslv - %Determine last character of key - prepost = 'LV'; - smallanimal=false; - if SET(no).EDV~=0 && ~isnan(SET(no).EDV) - smallanimal = SET(no).EDV<=1;% && SET(no).EDV~=0; - elseif SET(no).ESV~=0 && ~isnan(SET(no).ESV) - smallanimal = SET(no).ESV<=1; - end - - if smallanimal - unitV=['\mu', 'l']; - unitg='mg'; - unitcorr=1000; - end - if isnan(SET(no).LVM(SET(no).EDT)) && ~(SET(no).LVM(SET(no).EDT)>0) - lvmedt = bla{1}; - else - lvmedt = num2str(round(unitcorr*SET(no).LVM(SET(no).EDT)*1.05)); - end - - if isnan(SET(no).LVM(SET(no).EST)) - lvmest = bla{1}; - else - lvmest = num2str(round(unitcorr*SET(no).LVM(SET(no).EST)*1.05)); - end - updatestruct.([prepost 'M']) = sprintf('%s / %s',lvmedt,lvmest); - updatestruct.([prepost 'EDV']) = round(unitcorr*SET(no).EDV); - updatestruct.([prepost 'ESV']) = round(unitcorr*SET(no).ESV); - updatestruct.([prepost 'SV']) = round(unitcorr*SET(no).SV); - updatestruct.([prepost 'EF']) = round(100*SET(no).EF); - updatestruct.([prepost 'CO']) = (SET(no).HeartRate*SET(no).SV)/1000; - - - g.AxesTables.volume.updateUnit([prepost 'M'],unitg,true); - g.AxesTables.volume.updateUnit([prepost 'EDV'],unitV,true); - g.AxesTables.volume.updateUnit([prepost 'ESV'],unitV,true); - g.AxesTables.volume.updateUnit([prepost 'SV'],unitV,true); - -% title{1} = sprintf('LV [Image Stack %d]',no); - end - updatestruct.LVHR = round(SET(no).HeartRate); - %set(DATA.Handles.lvstackpushbutton,'String',sprintf('Stack #%d',no)); - else - %set(DATA.Handles.lvstackpushbutton,'String','Set stack'); + %------------------------------------------ + function updatervreport(g) + %------------------------------------------ + global SET NO + %for segment cmr we always use the values in the NO + no = NO; + + c = cell(1,6); + + if ~isempty(SET) && ~isempty(no) + rvmEDT = SET(no).RVM(SET(no).EDT)*1.05; + rvmEST = SET(no).RVM(SET(no).EST)*1.05; + rvedv = SET(no).RVEDV; + rvesv = SET(no).RVESV; + rvsv = SET(no).RVSV; + if rvmEDT > 0 && rvmEDT < 1 + %convert to milligram + rvmEDT = 1000*rvmEDT; + rvmEST = 1000*rvmEST; + g.Handles.rvheadertext.String{1} = 'ED/ES LVM (mg)'; + else + g.Handles.rvheadertext.String{1} = 'ED/ES LVM (g)'; end - - fnames = fieldnames(updatestruct); - for floop = 1:numel(fnames) - fname = fnames{floop}; - g.AxesTables.volume.updateKey(fname,updatestruct.(fname),true); + + if rvedv > 0 && rvedv < 1 + %convert to mikroliters + rvedv = 1000*rvedv; + g.Handles.rvheadertext.String{2} = ['RVEDV (',char(181),'l)']; + rvesv = 1000*rvesv; + g.Handles.rvheadertext.String{3} = ['RVESV (',char(181),'l)']; + rvsv = 1000*rvsv; + g.Handles.rvheadertext.String{4} = ['RVSV (',char(181),'l)']; + else + g.Handles.rvheadertext.String{2} = 'RVEDV (ml)'; + g.Handles.rvheadertext.String{3} = 'RVESV (ml)'; + g.Handles.rvheadertext.String{4} = 'RVSV (ml)'; end - - % -- RV -- - s = []; - s.RVM = bla; - s.RVEDV = bla; - s.RVESV = bla; - s.RVSV = bla; - s.RVEF = bla; -% s.RVHR = bla; - updatestruct = s; - % title{2} = 'RV'; - unitV='ml'; %default volume unit - unitg='g'; - unitcorr=1; %correction for volume unit - - if ~isempty(DATA.RVNO) % isfield(DATA,'RVNO') && - no = DATA.RVNO; - hasrv = ~isempty(SET(no).RVEpiX) || ~isempty(SET(no).RVEndoX); - - if hasrv - %Determine last character of key - prepost = 'RV'; - -% smallanimal=SET(no).RVEDV<=1 && SET(no).RVEDV~=0; - smallanimal=false; - if SET(no).RVEDV~=0 - smallanimal = SET(no).RVEDV<=1;% && SET(no).EDV~=0; - elseif SET(no).RVESV~=0 - smallanimal = SET(no).RVESV<=1; - end - - if smallanimal - unitV=['\mu' 'l']; - unitg='mg'; - unitcorr=1000; - end - - if isnan(SET(no).RVM(SET(no).EDT)) - rvmedt = bla{1}; - else - rvmedt = num2str(round(unitcorr*SET(no).RVM(SET(no).EDT)*1.05)); - end - - if isnan(SET(no).RVM(SET(no).EST)) - rvmest = bla{1}; - else - rvmest = num2str(round(unitcorr*SET(no).RVM(SET(no).EST)*1.05)); - end - updatestruct.([prepost 'M']) = sprintf('%s / %s',rvmedt,rvmest); - updatestruct.([prepost 'EDV']) = round(unitcorr*SET(no).RVEDV); - updatestruct.([prepost 'ESV']) = round(unitcorr*SET(no).RVESV); - updatestruct.([prepost 'SV']) = round(unitcorr*SET(no).RVSV); - updatestruct.([prepost 'EF']) = round(100*SET(no).RVEF); - - g.AxesTables.volume.updateUnit([prepost 'M'],unitg,true); - g.AxesTables.volume.updateUnit([prepost 'EDV'],unitV,true); - g.AxesTables.volume.updateUnit([prepost 'ESV'],unitV,true); - g.AxesTables.volume.updateUnit([prepost 'SV'],unitV,true); + c{1} = round(rvmEDT); + c{2} = round(rvmEST); + c{3} = round(rvedv); + c{4} = round(rvesv); + c{5} = round(rvsv); + c{6} = round(100*SET(no).RVEF); + end + + c_inds = cellfun(@(x) isempty(x) || isnan(x) || x == 0,c); + [c{c_inds}] = deal('---'); + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.rvreporttext.String = sprintf('%s / %s \n%s \n%s \n%s \n%s',c{:}); + set(g.Handles.rvreporttext,'FontSize',g.fontsizeincm); + g.Handles.rvheadertext.FontSize = g.fontsizeincm; - -% title{2} = sprintf('RV [Image Stack %d]',no); + end + + %------------------------------------------ + function updateflowreport(g) + %------------------------------------------ + global SET NO + %for segment cmr we always use the values in the FlowNO + no = NO; + c = cell(1,6); +% set(g.Handles.flowheaderroitext,'String','ROI-x'); + if ~isempty(SET) && ~isempty(no) + if isfield(SET(no), 'Parent') + if ~isempty(SET(no).Parent) + %reset no to the magnitude image + no = SET(no).Parent; end -% updatestruct.RVHR = round(SET(no).HeartRate); - %set(DATA.Handles.rvstackpushbutton,'String',sprintf('Stack #%d',no)); - else - %set(DATA.Handles.rvstackpushbutton,'String','Set stack'); end - - fnames = fieldnames(updatestruct); - for floop = 1:numel(fnames) - fname = fnames{floop}; - g.AxesTables.volume.updateKey(fname,updatestruct.(fname),true); + end + roinbr =[]; + if ~isempty(SET) && ~isempty(no) + if ~isempty (SET(no).RoiCurrent) + roinbr = SET(no).RoiCurrent; end - - - -% g.AxesTables.volume.updateTitle(title); - g.AxesTables.volume.draw(); end - %--------------------------- - function flowreportupdate(g) - %--------------------------- - %Update flow report in axestables - - global SET DATA NO - - updatestruct = struct(... - 'ROI', '',... - 'Netvol', '---',... % 'Forward', '---',... - 'Backward', '---',... - 'Regfrac', '---',... - 'FlowCO', '---' ,... - 'FlowHR', '---'); - name.ROI = 'ROI'; - %set(DATA.Handles.flowstackpushbutton,'String','Set stack'); -% title{1} = 'Flow'; - if ~isempty(DATA.FlowNO) && ~isempty(DATA.FlowROI) - no = DATA.FlowNO; - roinbr = DATA.FlowROI; - %Condition for non-time resolved Phase Contrast Flow measurement - if length(SET(no).Roi(roinbr).T) == 1 && ~isempty(SET) && ~isempty(no) && SET(no).RoiN > 0 && ~isempty(SET(no).Flow.Result) && not(isempty(roinbr)) && length(SET(no).Flow.Result)>=roinbr && isfield(SET(no).Flow.Result(roinbr),'nettotvol') %For no time resolved Flow data - updatestruct.Netvol = SET(no).Flow.Result(roinbr).nettotvol; - updatestruct.Backward = SET(no).Flow.Result(roinbr).negflow; - updatestruct.Regfrac ='---'; - updatestruct.FlowCO='---'; - updatestruct.FlowHR='---'; - name.ROI = SET(no).Roi(roinbr).Name; - - %Update names in tables structures and units - g.AxesTables.flow.updateName('Netvol','NetFlow',true); - g.AxesTables.flow.updateUnit('Netvol','ml/s',true); - g.AxesTables.flow.updateName('Backward','NegFlow',true); - g.AxesTables.flow.updateUnit('Backward','ml/s',true); - - elseif ~isempty(SET) && ~isempty(no) && SET(no).RoiN > 0 && ~isempty(SET(no).Flow.Result) && not(isempty(roinbr)) && length(SET(no).Flow.Result)>=roinbr && isfield(SET(no).Flow.Result(roinbr),'nettotvol') - - updatestruct.ROI = ''; - updatestruct.Netvol = SET(no).Flow.Result(roinbr).nettotvol; -% updatestruct.Forward = SET(no).Flow.Result(roinbr).netforwardvol; - updatestruct.Backward = SET(no).Flow.Result(roinbr).netbackwardvol; - updatestruct.Regfrac = SET(no).Flow.Result(roinbr).regfrac; + +% if ~isempty(SET) && ~isempty(no) && ~isempty(SET(no).Flow)... +% && ~isempty(SET(no).RoiCurrent) && ~isempty(SET(no).Flow.Result)... + if ~isempty(SET)&& ~isempty(no) && ~isempty(SET(no).Flow) && ~isempty(roinbr) &&... + ~isempty(SET(no).Flow.Result) && ~(length(SET(no).Flow.Result)< roinbr)... + && ~strcmp(SET(no).Roi(roinbr).Name, 'Static tissue') + + set(g.Handles.flowheaderroitext,'String',SET(no).Roi(SET(no).RoiCurrent).Name); + if SET(no).Flow.Result(roinbr).nettotvol > 100 + c{1} = round(SET(no).Flow.Result(roinbr).nettotvol); + else + c{1} = round(SET(no).Flow.Result(roinbr).nettotvol*100)/100; + end + c{2} = round(SET(no).Flow.Result(roinbr).netforwardvol*100)/100; + c{3} = round(SET(no).Flow.Result(roinbr).netbackwardvol*100)/100; + if SET(no).Flow.Result(roinbr).regfrac > 100 + c{4} = round(SET(no).Flow.Result(roinbr).regfrac); + else + c{4} = round(SET(no).Flow.Result(roinbr).regfrac*100)/100; + end + %define heart rate if not(isfield(SET(no).Flow,'HeartRate')) || isempty(SET(no).Flow.HeartRate) temphr = (60/(SET(no).TSize*SET(no).TIncr)); @@ -1012,259 +591,193 @@ function flowreportupdate(g) SET(no).Flow.HeartRate = temphr; end end - updatestruct.FlowCO = SET(no).Flow.Result(roinbr).nettotvol*SET(no).Flow.HeartRate/1000; - updatestruct.FlowHR = SET(no).Flow.HeartRate; %round((60/(SET(no).TSize*SET(no).TIncr))); %SET(no).HeartRate; - nop = SET(no).Flow.PhaseNo; - if ~isempty(SET(nop).Flow.PhaseCorr) - if ~isfield(SET(nop).Flow,'PhaseCorrTimeResolved') - mywarning('Incompatible eddy current correction. Correction reset.',DATA.GUI.Segment); - SET(nop).Flow.PhaseCorr = []; - name.ROI = SET(no).Roi(roinbr).Name; - else - name.ROI = sprintf('%s [Eddy]',SET(no).Roi(roinbr).Name); - end - else - name.ROI = SET(no).Roi(roinbr).Name; + c{5} = round(SET(no).Flow.Result(roinbr).nettotvol*SET(no).Flow.HeartRate/1000*100)/100; + c{6} = round(SET(no).Flow.HeartRate); %SET(no).HeartRate; + else +% %define heart rate +% if not(isempty(no)) && (not(isfield(SET(no).Flow,'HeartRate')) || isempty(SET(no).Flow.HeartRate)) +% temphr = (60/(SET(no).TSize*SET(no).TIncr)); +% if temphr < 35 +% reportflow('defineheartrate',no); +% else +% SET(no).Flow.HeartRate = temphr; +% end +% end + + end + + if ~isempty(roinbr) +% c{6} = round(SET(no).Flow.HeartRate); + set(g.Handles.flowheaderroitext,'String',SET(no).Roi(roinbr).Name); + end + + c_inds = cellfun(@(x) isempty(x) || isnan(x) || x == 0,c); + [c{c_inds}] = deal('---'); + + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.flowreporttext.String = sprintf('%s \n%s \n%s \n%s \n%s \n%s \n%s',c{:}); + set(g.Handles.flowreporttext,'FontSize',g.fontsizeincm); + set(g.Handles.flowheadertext,'FontSize',g.fontsizeincm); + set(g.Handles.flowheaderroitext,'FontSize',g.fontsizeincm); + end + + %------------------------- + function updateflowaxes(g) + %------------------------- + %Update the flow report axes in main GUI + global SET NO + roinbr=[]; + no = NO; + if ~isempty(SET) && ~isempty(no) + if isfield(SET(no), 'Parent') + if ~isempty(SET(no).Parent) + % reset no to the magnitude image + no = SET(no).Parent; end - %set(DATA.Handles.flowstackpushbutton,'String',sprintf('Stack #%d',no)); end - end - DATA.updateflowaxes; - - g.AxesTables.flow.updateName('ROI',name.ROI,true); - fnames = fieldnames(updatestruct); - for floop = 2:numel(fnames) - fname = fnames{floop}; - g.AxesTables.flow.updateKey(fname,updatestruct.(fname),true); end -% g.AxesTables.flow.updateTitle(title); - g.AxesTables.flow.draw(); - %set(g.Handles.flowuipanel,'Visible','on'); - + if ~isempty(SET) && ~isempty(no) + roinbr = SET(no).RoiCurrent; end + if isempty(SET) || isempty(no) || SET(no).TSize<2 || isempty(roinbr)|| isempty(SET(no).Flow) || isempty(SET(no).Flow.Result) || length(SET(no).Flow.Result)< roinbr || isempty(SET(no).Flow.Result(roinbr)) || isempty(SET(no).Flow.Result(roinbr).netflow) + set([g.Handles.flowaxes;g.Handles.flowaxes.Children;... + g.Handles.flowaxes.XLabel;g.Handles.flowaxes.YLabel],'Visible','off'); + + else + %Time resolved + t = SET(no).TimeVector*1000; - %--------------------------------- - function measurementreportupdate(g) - %--------------------------------- - %Update scar report in axestables + set([g.Handles.flowaxes;g.Handles.flowaxes.Children;... + g.Handles.flowaxes.XLabel;g.Handles.flowaxes.YLabel],'Visible','on'); + + %set the xlim of the plot + xlim(g.Handles.flowaxes,[t(1),t(end)]) + + %flow curve + netflow = SET(no).Flow.Result(roinbr).netflow; + + %plot in color of roi + curvecolor=SET(no).Roi(roinbr).LineSpec(1); + + g.Handles.flowcurve.XData = t; + g.Handles.flowcurve.YData = netflow; + g.Handles.flowcurve.Color = curvecolor; + + % set y-lim dependent on netflow values + minflow = min(netflow); + maxflow = max(netflow); + set(g.Handles.flowaxes,'ylim',[floor((minflow-50)/100)*100 ceil((maxflow+50)/100)*100]); + + %outer time bars + g.Handles.outerbarsflow.XData = [t(1) t(1) nan t(end) t(end)]; + g.Handles.outerbarsflow.YData = [ylim(g.Handles.flowaxes) nan ylim(g.Handles.flowaxes)]; + + %current time + g.Handles.timebarflow.XData = [t(SET(no).CurrentTimeFrame) t(SET(no).CurrentTimeFrame)]; + g.Handles.timebarflow.YData = ylim(g.Handles.flowaxes); + + %the flow axeshelpers + temp = get(g.Handles.flowaxes,'ylim'); + ttemp = [t;t;nan(size(t))]; + temp = [repmat(temp(1),size(t));repmat(temp(1)+0.1*(temp(2)-temp(1)),size(t));nan(size(t))]; + g.Handles.flowaxeshelpers.XData = ttemp(:); + g.Handles.flowaxeshelpers.YData = temp(:); + + %the default assumption + g.Handles.flowtext.Position = [nan nan]; + if ~isempty(SET(SET(no).Flow.PhaseNo).Flow.PhaseCorr) + if ~isfield(SET(SET(no).Flow.PhaseNo).Flow,'PhaseCorrTimeResolved') + mywarning('Incompatible eddy current correction. Correction reset.',g.GUI.Segment); + else + g.Handles.flowtext.Position = [max(get(g.Handles.flowaxes,'XLim')),double(max(get(g.Handles.flowaxes,'YLim')))]; + end + end + end + end - global SET NO - + %------------------------------------------ + function updatemeasurementreport(g) + %------------------------------------------ + global SET NO + %for segment we always use the values in the NO no = NO; - bla = {'---'}; + + if ~isempty(SET) && ~isempty(no) + %different measurements we want to display hasscar = ~isempty(SET(no).Scar) && ~isempty(SET(no).Scar.Percentage); hasmar = ~isempty(SET(no).MaR) && ~isempty(SET(no).MaR.Result); - hasflow = ~isempty(SET) && SET(no).RoiN > 0 && isfield(SET(no).Flow,'nettotvol'); - hasmmode = (strcmp(g.ViewPanelsType{g.CurrentPanel},'mmodespatial') ... - || strcmp(g.ViewPanelsType{g.CurrentPanel},'mmodetemporal')); hasatrialscar = isfield(SET(no),'AtrialScar') && ~isempty(SET(no).AtrialScar) && ~isempty(SET(no).AtrialScar.Percentage); - updatestruct = []; + else + hasscar = false; + hasmar = false; + hasatrialscar = false; + end + + if ~any([hasscar hasmar hasatrialscar]) + g.Handles.measurementuipanel.Visible = 'off'; + g.Handles.flowuipanel.Visible = 'on'; + else + g.Handles.measurementuipanel.Visible = 'on'; + g.Handles.flowuipanel.Visible = 'off'; + end if hasscar scarpro2mlcoeff=sum(SET(no).Scar.MyocardMask(:))/100/1000*SET(no).ResolutionX*SET(no).ResolutionY*(SET(no).SliceGap+SET(no).SliceThickness); - scarml=round(10*SET(no).Scar.Percentage*scarpro2mlcoeff)/10; + scarml=round(10*SET(no).Scar.Percentage*scarpro2mlcoeff)/10; end - + if hasmar && hasscar + c = cell(1,4); + c{1} = scarml; + c{2} = round(10*SET(no).Scar.Percentage)/10; + c{3} = round(10*SET(no).Scar.MOPercentage)/10; + c{4} = (round(SET(no).MaR.Percentage(SET(no).EDT))); + c{5} = (round(SET(no).MaR.Percentage(SET(no).EST))); - updatestruct.m1 = scarml;%round(SET(no).Scar.Percentage);%([SET(no).EDT, SET(no).EST])); - updatestruct.m2 = round(10*SET(no).Scar.Percentage)/10;%round(SET(no).Scar.Percentage);%([SET(no).EDT, SET(no).EST])); - updatestruct.m3 = round(10*SET(no).Scar.MOPercentage)/10; - updatestruct.m4 = [num2str(round(SET(no).MaR.Percentage(SET(no).EDT))),'/',num2str(round(SET(no).MaR.Percentage(SET(no).EST)))]; + c_inds = cellfun(@(x) isempty(x) || isnan(x),c); + [c{c_inds}] = deal('---'); + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.measurementheadertext.String = sprintf('%s\n%s\n%s\n%s','Scar (ml)','Scar (%)','MO (%)','ED/ES MaR (%)'); + g.Handles.measurementreporttext.String = sprintf('%s\n%s\n%s\n%s/%s',c{:}); - name.m1 = 'Scar'; - unit.m1 = 'ml'; - name.m2 = 'Scar'; - unit.m2 = '%'; - name.m3 = 'MO'; - unit.m3 = '%'; - name.m4 = 'ED/ES MaR'; - unit.m4 = '%'; - title{1} = sprintf('Scar & MaR'); - elseif hasscar - %updatestruct.m1 = round(SET(no).LVM(SET(no).EDT)*1.05); - updatestruct.m1 = scarml;%round(SET(no).Scar.Percentage);%([SET(no).EDT, SET(no).EST])); - updatestruct.m2 = round(10*SET(no).Scar.Percentage)/10; - updatestruct.m3 = round(10*SET(no).Scar.MOPercentage)/10; + c = cell(1,3); + c{1} = scarml; + c{2} = round(10*SET(no).Scar.Percentage)/10; + c{3} = round(10*SET(no).Scar.MOPercentage)/10; - %name.m1 = 'LVM'; - name.m1 = 'Scar'; - %unit.m1 = 'g'; - unit.m1 = 'ml'; + c_inds = cellfun(@(x) isempty(x) || isnan(x),c); + [c{c_inds}] = deal('---'); + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.measurementheadertext.String = sprintf('%s\n%s\n%s','Scar (ml)','Scar (%)','MO (%)'); + g.Handles.measurementreporttext.String = sprintf('%s\n%s\n%s',c{:}); - name.m2 = 'Scar'; - unit.m2 = '%'; - - name.m3 = 'MO'; - unit.m3 = '%'; - - updatestruct.m4 = bla; - name.m4 = bla; - unit.m4 = ''; - - title{1} = sprintf('Scar'); - - elseif hasmar - %updatestruct.m1 = round(SET(no).LVM(SET(no).EDT)*1.05); - updatestruct.m1 = [num2str(round(SET(no).MaR.Percentage(SET(no).EDT))),'/',num2str(round(SET(no).MaR.Percentage(SET(no).EST)))];%round(SET(no).MaR.Percentage([SET(no).EDT,SET(no).EST])); - %name.m1 = 'LVM'; - name.m1 = 'ED/ES MaR'; - %unit.m1 = 'g'; - unit.m1 = '%'; - - updatestruct.m2 = bla; - name.m2 = bla; - unit.m2 = ''; - - updatestruct.m3 = bla; - name.m3 = bla; - unit.m3 = ''; - - updatestruct.m4 = bla; - name.m4 = bla; - unit.m4 = ''; - title{1} = sprintf('MaR'); - - elseif hasatrialscar - updatestruct.m1 = round(10*SET(no).AtrialScar.Percentage)/10; - - name.m1 = 'Atrial Scar'; - unit.m1 = '%'; - - updatestruct.m2 = bla; - name.m2 = bla; - unit.m2 = ''; - - updatestruct.m3 = bla; - name.m3 = bla; - unit.m3 = ''; - - updatestruct.m4 = bla; - name.m4 = bla; - unit.m4 = ''; - - title{1} = sprintf('Atrial Scar'); + elseif hasmar + c = cell(1,2); + c{1} = round(SET(no).MaR.Percentage(SET(no).EDT)); + c{2} = round(SET(no).MaR.Percentage(SET(no).EST)); + + c_inds = cellfun(@(x) isempty(x) || isnan(x),c); + [c{c_inds}] = deal('---'); + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.measurementheadertext.String = sprintf('%s','ED/ES MaR (%)'); + g.Handles.measurementreporttext.String = sprintf('%s/%s',c{:}); -% elseif hasflow -% rloop = 1; -% updatestruct.m1 = SET(no).Flow.nettotvol(rloop); -% updatestruct.m2 = SET(no).Flow.regfrac(rloop); -% name.m1 = 'Net vol'; -% name.m2 = 'Regurg. frac.'; -% unit.m1 = 'ml'; -% unit.m2 = '%'; -% title{1} = sprintf('Flow'); - elseif hasmmode && ~hasflow - [dist,timedist] = calcfunctions('calcmmodedists',no); - updatestruct.m1 = dist; - updatestruct.m2 = timedist; - name.m1 = 'Distance'; - name.m2 = 'Time'; - unit.m1 = 'mm'; - unit.m2 = 'ms'; - updatestruct.m3 = bla; - name.m3 = bla; - unit.m3 = ''; + elseif hasatrialscar + c = cell(1,1); + c{1} = round(10*SET(no).AtrialScar.Percentage)/10; - updatestruct.m4 = bla; - name.m4 = bla; - unit.m4 = ''; - title{1} = sprintf('Mmode: Distance between lines'); - else - %bla = {'---'}; - updatestruct.m1 = bla; - updatestruct.m2 = bla; - updatestruct.m3 = bla; - updatestruct.m4 = bla; - name.m1 = bla; - name.m2 = bla; - name.m3 = bla; - name.m4 = bla; - unit.m1 = ''; - unit.m2 = ''; - unit.m3 = ''; - unit.m4 = ''; - title{1} = ''; - end - - - if hasscar || hasmar || hasatrialscar || (hasmmode && ~hasflow) - set(g.Handles.measurementuipanel,'Visible','on'); - %set(g.Handles.measurementslideruipanel,'Visible','on'); - set(g.Handles.flowuipanel,'Visible','off'); - %set(g.Handles.flowaxes,'Visible','off'); - %set(g.Handles.flowresultaxes,'Visible','off'); - %set(g.Handles.measurementresultaxes,'Visible','on'); - g.AxesTables.measurement.show; - %viability('sliderupdate') -% if hasscar -% set([g.Handles.slider1,g.Handles.slider2, g.Handles.slider1edit,g.Handles.slider2edit],'Visible', 'on') -% else -% set([g.Handles.slider1,g.Handles.slider2, g.Handles.slider1edit,g.Handles.slider2edit],'Visible', 'off') -% end - %else - % viability('sliderupdate') + c_inds = cellfun(@(x) isempty(x) || isnan(x),c); + [c{c_inds}] = deal('---'); + c = cellfun(@(x) num2str(x),c,'UniformOutput',false); + g.Handles.measurementheadertext.String = sprintf('%s','Atrial Scar (%)'); + g.Handles.measurementreporttext.String = sprintf('%s',c{:}); end viability('sliderupdate') - - fnames = fieldnames(updatestruct); - for floop = 1:numel(fnames) - fname = fnames{floop}; - g.AxesTables.measurement.updateKey(fname,updatestruct.(fname),true); - g.AxesTables.measurement.updateName(fname,name.(fname),true); - g.AxesTables.measurement.updateUnit(fname,unit.(fname),true); - end - g.AxesTables.measurement.updateTitle(title); - g.AxesTables.measurement.draw(); - - if not(hasscar) && not(hasmar) && not(hasatrialscar) && not(hasflow) && not(hasmmode) - g.AxesTables.measurement.hide; - set(g.Handles.measurementuipanel,'Visible','off'); -% val=get(g.Handles.hideallpanelscheckbox,'value'); -% if val==0 -% set(g.Handles.flowuipanel,'Visible','on'); - % end -% else -% xval = get(g.Handles.measurementresultaxes,'xlim'); -% yval = get(g.Handles.measurementresultaxes,'ylim'); -% hold(g.Handles.measurementresultaxes,'on'); -% plot(g.Handles.measurementresultaxes,[xval(1) xval(2) xval(2) xval(1) xval(1)],[yval(1) yval(1) yval(2) yval(2) yval(1)],'k-'); -% hold(g.Handles.measurementresultaxes,'off'); - end - + set(g.Handles.measurementheadertext,'FontSize',g.fontsizeincm); + set(g.Handles.measurementreporttext,'FontSize',g.fontsizeincm); end - - %--------------------------------- - function measurementreportclear(g) - %--------------------------------- - %Clear measurement report in axestables - - updatestruct = []; - bla = {'---'}; - updatestruct.m1 = bla; - updatestruct.m2 = bla; - name.m1 = bla; - name.m2 = bla; - unit.m1 = ''; - unit.m2 = ''; - title{1} = ''; - - fnames = fieldnames(updatestruct); - for floop = 1:numel(fnames) - fname = fnames{floop}; - g.AxesTables.measurement.updateKey(fname,updatestruct.(fname),true); - g.AxesTables.measurement.updateName(fname,name.(fname),true); - g.AxesTables.measurement.updateUnit(fname,unit.(fname),true); - end - g.AxesTables.measurement.updateTitle(title); - g.AxesTables.measurement.draw(); - - g.AxesTables.measurement.hide; - set(g.Handles.measurementuipanel,'Visible','off'); - end - %------------------------ function failedaborted(g) @@ -1289,19 +802,7 @@ function checkversion(g) checkversion(); end end - - %--------------------------- - function updateicons(g,mode) - %--------------------------- - %Update icons when new mode is selected - %Overloads main GUI method. - set([g.Handles.t2starpushbutton g.Handles.perfusionpushbutton ], 'visible', 'off', 'enable','off'); - if nargin<2 - mode = g.CurrentTheme; - end; - updateicons@maingui(g,mode); - end - + %----------------------- function initbullseye(g) %----------------------- @@ -1314,28 +815,98 @@ function initbullseyeslices(g) %#ok %Autoselects slices with myocardium in them before GUI is opened end - end - - methods(Access = 'protected') - - %--------------------------------------- - function switchtoimagestack_part2(g, no) - %--------------------------------------- - %switchtoimagestack continued. Overloads method in maingui. - if ~isempty(g.BlockingFigs) - deleteguis=yesno('Need to close all reviewing windows before changing current image stack. Do you want to do that now?',[],g.GUI.Segment); - if deleteguis - try - delete(g.BlockingFigs); - catch %#ok - end; - end - end; - switchtoimagestack_part2@maingui(g,no); +% %------------------------------------------------- +% function [stri,lstr] = measureasklabel(~,measureind) +% %------------------------------------------------- +% %Ask measurement +% +% s = myinputdlg({'Enter name'},'Name',1,{sprintf('Measure_%d',measureind)}); +% if isempty(s) +% stri = ''; +% lstr = ''; +% else +% stri = s{1}; +% lstr = s{1}; +% end +% +% end + %------------------------------------------------- + function [stri,lstr] = measureasklabel(g,measureind) + %------------------------------------------------- + %Ask measurement + + m = mymenu('Select measurement type',... + {'ASW (Anterior Septal Wall Thickness)',... + 'PLW (Posterior Lateral Wall Thickness)',... + 'ESD (End Systolic Dimension)',... + 'EDD (End Diastolic Dimension)',... + 'ESL (End Systolic Length)',... + 'EDL (End Diastolic Length)',... + 'AA (Ascending Aorta)',... + 'DA (Descending Aorta)',... + 'ARD (Aortic Root Diameter)',... + 'AL (Aortic Length)',... + 'RVmaj (RV Major Axis)',... + 'RVmin (RV Minor Axis)',... + 'User defined ...'},g.GUI.Segment); + + switch m + case 0 + stri = ''; + lstr = ''; + return; + case 1 + stri = 'ASW'; + lstr = 'Anterior Septal Wall Thickness'; + case 2 + stri = 'PLW'; + lstr = 'Posterior Lateral Wall Thickness'; + case 3 + stri = 'ESD'; + lstr = 'End Systolic Dimension'; + case 4 + stri = 'EDD'; + lstr = 'End Diastolic Dimension'; + case 5 + stri = 'ESL'; + lstr = 'End Systolic Length'; + case 6 + stri = 'EDL'; + lstr = 'End Diastolic Length'; + case 7 + stri = 'AA'; + lstr = 'Ascending Aorta'; + case 8 + stri = 'DA'; + lstr = 'Descending Aorta'; + case 9 + stri = 'ARD'; + lstr = 'Aortic Root Diameter'; + case 10 + stri = 'AL'; + lstr = 'Aortic Length'; + case 11 + stri = 'RVmaj'; + lstr = 'RV Major Axis'; + case 12 + stri = 'RVmin'; + lstr = 'RV Minor Axis'; + case 13 + s = myinputdlg({'Enter name'},'Name',1,{sprintf('Measure_%d',measureind)}); + if isempty(s) + stri = ''; + lstr = ''; + else + stri = s{1}; + lstr = s{1}; + end + end end - end + + end + methods(Static) %--------------------- @@ -1375,7 +946,7 @@ function licensemsg(m) slc = SET(NO).CurrentSlice; SET(NO).RVEndoX(:,tf2,slc) = SET(NO).RVEndoX(:,tf,slc); SET(NO).RVEndoY(:,tf2,slc) = SET(NO).RVEndoY(:,tf,slc); - segment('setcurrenttimeframe',tf2); + viewfunctions('switchtimeframe',1,true); %segment('setcurrenttimeframe',tf2); segment('updatevolume'); end end diff --git a/source/segmenthelp.p b/source/segmenthelp.p index 42a29f4..0798353 100644 Binary files a/source/segmenthelp.p and b/source/segmenthelp.p differ diff --git a/source/segmentservermonitor.fig b/source/segmentservermonitor.fig index 7309c18..2cc76f3 100644 Binary files a/source/segmentservermonitor.fig and b/source/segmentservermonitor.fig differ diff --git a/source/segmentservermonitor.p b/source/segmentservermonitor.p index 32501c3..fba75c3 100644 Binary files a/source/segmentservermonitor.p and b/source/segmentservermonitor.p differ diff --git a/source/segmentstrainimage.png b/source/segmentstrainimage.png new file mode 100644 index 0000000..ff405e3 Binary files /dev/null and b/source/segmentstrainimage.png differ diff --git a/source/segmentview.m b/source/segmentview.m index ab11330..df0f9e3 100644 --- a/source/segmentview.m +++ b/source/segmentview.m @@ -12,7 +12,7 @@ if nargin==0 varargin = {'init'}; -end; +end macro_helper(varargin{:}); [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard @@ -23,15 +23,11 @@ %Initialize GUI global DATA -%This turns off the icon in Segment -%Change this line when icon in Segment... -%set(DATA.Handles.reportlongaxisicon,'state','off'); - %Check if no data loaded if ~DATA.DataLoaded myfailed('You need to have data loaded to run this GUI.'); return; -end; +end %Real initialization DATA.GUI.SegmentView = mygui('segmentview.fig'); %Create object and store in global the variable DATA @@ -80,7 +76,7 @@ set([gui.handles.renamepushbutton ... gui.handles.deletepushbutton ... gui.handles.viewpushbutton],'enable','on'); -end; +end %Update handles set(gui.handles.viewlistbox,'String',views); @@ -121,7 +117,7 @@ set([gui.handles.renamecontrastpushbutton ... gui.handles.deletecontrastpushbutton ... gui.handles.applypushbutton],'enable','on'); -end; +end %Update handles set(gui.handles.windowlistbox,'String',windows); @@ -159,7 +155,7 @@ %---------------------------------- function loadcontrastfrompreset(cv) %---------------------------------- -global SET NO +global SET NO DATA if isfield(cv.conbri,'Contrast') SET(NO).IntensityMapping.Contrast = cv.conbri.Contrast; SET(NO).IntensityMapping.Brightness = cv.conbri.Brightness; @@ -169,7 +165,8 @@ function loadcontrastfrompreset(cv) SET(NO).IntensityMapping.Contrast = contrast; SET(NO).IntensityMapping.Brightness = brightness; end -drawfunctions('drawcontrastimage',NO); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); %----------------------- function delete_Callback %#ok @@ -191,7 +188,7 @@ function loadcontrastfrompreset(cv) v = get(gui.handles.viewlistbox,'value'); if ~isequal(v,1) set(gui.handles.viewlistbox,'value',v-1); -end; +end %Call update to reflect changes update; @@ -216,7 +213,7 @@ function loadcontrastfrompreset(cv) v = get(gui.handles.windowlistbox,'value'); if ~isequal(v,1) set(gui.handles.windowlistbox,'value',v-1); -end; +end %Call update to reflect changes updatecontrast; @@ -391,13 +388,13 @@ function loadcontrastfrompreset(cv) %Please note these need to be in correct order if isshift hotkey = [hotkey 'Shift-']; -end; +end if isctrl hotkey = [hotkey 'Ctrl-']; -end; +end if isalt hotkey = [hotkey 'Alt-']; -end; +end hotkey = [hotkey hotkeystring]; set(gui.handles.hotkeytext,'string',hotkey); @@ -423,13 +420,13 @@ function loadcontrastfrompreset(cv) %Please note these need to be in correct order if isshift hotkey = [hotkey 'Shift-']; -end; +end if isctrl hotkey = [hotkey 'Ctrl-']; -end; +end if isalt hotkey = [hotkey 'Alt-']; -end; +end hotkey = [hotkey hotkeystring]; set(gui.handles.contrasthotkeytext,'string',hotkey); @@ -690,7 +687,7 @@ function deleteviewfrompreset(v) viewsarray = gui.viewsarray; %#ok save(gui.viewsfile,'viewsarray'); %Store to file else - myfailed('Operation cancelled.'); +% myfailed('Operation cancelled.'); end %--------------------------------- @@ -709,7 +706,7 @@ function deletewindowfrompreset(v) windowsarray = gui.windowsarray; %#ok save(gui.windowsfile,'windowsarray'); %Store to file else - myfailed('Operation cancelled.'); +% myfailed('Operation cancelled.'); end %------------------------------ @@ -718,7 +715,7 @@ function loadviewfrompreset(pv) %Code to bring it up! nos = pv.match; shape = pv.matrix; -drawfunctions('drawimageview',nos,shape,pv.panelstype); +viewfunctions('setview',shape(1),shape(2),nos,pv.panelstype); % DATA.ViewPanelsType = pv.panelstype; % DATA.ViewPanels = nos; % DATA.ViewIM = cell(1,numel(nos)); @@ -750,7 +747,7 @@ function keypressed(key) %#ok loadviewfrompreset(viewsarray(keymatch)); return end -end; +end if exist('windowsarray','var') windowkeys = {windowsarray.hotkey}; @@ -759,4 +756,4 @@ function keypressed(key) %#ok loadcontrastfrompreset(windowsarray(keymatch)); return end -end; +end diff --git a/source/segpref.fig b/source/segpref.fig index f548769..2f028ba 100644 Binary files a/source/segpref.fig and b/source/segpref.fig differ diff --git a/source/segpref.m b/source/segpref.m deleted file mode 100644 index 2f33532..0000000 --- a/source/segpref.m +++ /dev/null @@ -1,1548 +0,0 @@ -function varargout = segpref(varargin) -%SEGPREF Helper function for SEGMENT, GUI for preferences - -%Einar Heiberg - -global DATA - -if nargin == 0 % LAUNCH GUI - - DATA.setprefhandles; - update; - fig = DATA.PrefHandles.fig; - translation.translatealllabels(fig); - if nargout > 0 - varargout{1} = fig; - end - -elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK - - try - macro_helper(varargin{:}); - if (nargout) - [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard - else - feval(varargin{:}); % FEVAL switchyard - end - catch me - mydispexception(me); - end - -end - -%-------------- -function update -%-------------- -global DATA - -DATA.updateprefhandles; - -%--------------------- -function undo_Callback %#ok -%--------------------- -%Loads from disk and graphical update -loadpreferences; -if isopengui('segpref.fig') - update; -end -if isopengui('segprefadvanced.fig') - updateadvanced; -end - -% %---------------------------- -% function init_userlogging -% %---------------------------- -% global DATA -% val = mygetvalue(DATA.PrefHandles.userloggingcheckbox) -% -% if val == 1 -% %Initiate log file. Overloaded in most other GUI's -% pathname = DATA.Pref.userpath; -% DATA.UserFile = [pathname filesep sprintf('segmentlog_%s.log',datestr(now,'yyyymmddHHMMSS'))]; -% fid = fopen(g.LogFile,'w'); -% if isequal(fid,-1) -% myfailed(dprintf('Could not create .log file %s.',g.LogFile)); -% else -% fclose(fid); %Close the file, to make it empty -% DATA.startlog(DATA.UserFile); %Start diary. -% end; -% end - - -%----------------------------- -function userlogging_Callback %#ok -%----------------------------- -%started the user logging - -global DATA -val = mygetvalue(DATA.PrefHandlesAdvanced.userloggingcheckbox); - -% [~,streng] = system('net localgroup Admin'); -% [~,strswe] = system('net localgroup Administratörer'); -usrname = getenv('USERNAME'); -% if isempty(regexp(streng,usrname,'once')) && isempty(regexp(strswe,usrname,'once')) -% myfailed('You do not have administrator priviliges') -% return -% end - -%Display message about potentially require admin rights. -adminrequirement; - -if val == 1 - answer = yesno(sprintf('You are currently logged in as %s. Do you wish to proceed?',usrname)); -else - str = sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),usrname,'User logging stopped.','-'); - DATA.adduserevent(str); - set(DATA.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); - DATA.Pref.UserLogging = 0; - return -end - -if answer~=1 - DATA.Pref.UserLogging = 0; - set(DATA.PrefHandlesAdvanced.userloggingcheckbox,'Value',0); - set(DATA.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); - return -end - -DATA.Pref.UserLogging = 1; -if val == 1 - %set path for storing current user. - if isempty(DATA.Pref.UserLogPath) - abort = setuserlogpath; - if abort - DATA.Pref.UserLogging = 0; - return - end - end - - DATA.init_userlogging - if DATA.Pref.UserLogging - set(DATA.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','on'); - else - set(DATA.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); - end - -else - DATA.Pref.UserLogging = 0; - set(DATA.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); -end - -%------------------------------ -function abort = setuserlogpath -%------------------------------ -% set the path for storing user logging - -global DATA -abort=0; -%set path for storing current user. -temp = myuigetdir(pwd,'Select folder for storing user information'); -if temp == 0 - mydisp('aborted by user') - abort = 1; - return -end -DATA.Pref.UserLogPath=[temp filesep sprintf('segmentuserlog.txt')]; - -fail = DATA.adduserevent(sprintf('%s\t%s\t%s\t%s','DATE','USER','EVENT','PATIENT ID')); - -if fail - set(DATA.PrefHandlesAdvanced.userloggingcheckbox,'Value',DATA.Pref.UserLogging); - set(DATA.PrefHandlesAdvanced.userlogpathtext,'String',DATA.Pref.UserLogPath); - set(DATA.PrefHandlesAdvanced.setuserlogpathpushbutton,'Enable','off'); - return -end - -DATA.adduserevent(sprintf('%s\t%s\t%s\t%s',datestr(now,'yyyy-mm-dd HH:MM'),getenv('USERNAME'),sprintf('Changed log path to %s',DATA.Pref.UserLogPath),'-')); -set(DATA.PrefHandlesAdvanced.userlogpathtext,'String',DATA.Pref.UserLogPath); - %set(DATA.PrefHandles.setuserlogpathstring,DATA.Pref.userpath) - -%---------------------------- -function setbackgroundcolor(backgroundcolor) %#ok -%---------------------------- -%set the background color for the main interface - -global DATA SET - -if nargin == 0 - mode = mygetvalue(DATA.PrefHandles.backgroundcolorpopupmenu); - switch mode - case 1 %Dark blue-grey - backgroundcolor=[0.94,0.94,0.94]; %[0.2118,0.2353,0.2824]; -% foregroundcolor=[0.94,0.94,0.94]; - case 2 %Light gray - backgroundcolor=[0.34,0.34,0.34]; %[0.94,0.94,0.94]; % -% foregroundcolor=[0 0 0]; - case 3 - backgroundcolor=[0 0 0]; -% foregroundcolor=[0.94,0.94,0.94]; - end -else - %this is default if not used new addon. - mode = 1; - - if all(backgroundcolor == [0.94 0.94 0.94]) %[0.2118,0.2353,0.2824]) - mode=1; -% foregroundcolor=[0.94,0.94,0.94]; - end - - if all(backgroundcolor == [0.34 0.34 0.34]) %[0.94,0.94,0.94]); %[0.34,0.34,0.34]) - mode=2; -% foregroundcolor=[0 0 0]; - end - - if all(backgroundcolor == [0,0,0]) - mode=3; - foregroundcolor=[0.94,0.94,0.94]; - end -end -DATA.Pref.GUIBackgroundColor = backgroundcolor; -DATA.GUISettings.BackgroundColor=DATA.Pref.GUIBackgroundColor; -DATA.GUISettings.ForegroundColor=foregroundcolor; -DATA.GUISettings.BoxAxesColor=[0.1 0.1 0.1]; -if mode == 3 % || mode == 1 - slidercolor=[0.5 0.5 0.5]; -else - slidercolor=[0.86 0.86 0.86]; -end - -set(DATA.fig,'Color',backgroundcolor); -set(DATA.Handles.barpanel,'BackgroundColor',backgroundcolor) -set(DATA.Handles.distancetext,'BackgroundColor',backgroundcolor) - -if mode==3 - set(DATA.Handles.distancetext,'Foreground',[1,1,1]) - set(get(DATA.Handles.timebaraxes,'Xlabel'),'Color','white'); - set(DATA.Handles.timebaraxes,'XColor','white'); - DATA.GUISettings.TimebarAxesColor='white'; -else - DATA.GUISettings.TimebarAxesColor='black'; - set(get(DATA.Handles.timebaraxes,'Xlabel'),'Color','black'); - set(DATA.Handles.timebaraxes,'XColor','black'); -end -set(DATA.Handles.flowuipanel,'BackgroundColor',backgroundcolor) -set(DATA.Handles.lvuipanel,'BackgroundColor',backgroundcolor) -set(DATA.Handles.measurementuipanel,'BackgroundColor',backgroundcolor) -set(DATA.Handles.reportpanel,'BackgroundColor',backgroundcolor) -set(DATA.Handles.slider1text,'BackgroundColor',backgroundcolor) -set(DATA.Handles.slider2text,'BackgroundColor',backgroundcolor) - -if mode == 3 %|| mode == 1 - set(DATA.Handles.volumeaxes,'Color',[0.34,0.34,0.34]) - set(DATA.Handles.flowaxes,'Color',[0.34,0.34,0.34]) - set(DATA.Handles.lvuipanel,'HighlightColor',[1,1,1]) - set(DATA.Handles.flowuipanel,'HighlightColor',[1,1,1]) - set(DATA.Handles.measurementuipanel,'HighlightColor',[1,1,1]) - set(DATA.Handles.timebaraxes,'Color',[0.34,0.34,0.34]) - set(DATA.Handles.timebaraxes,... - 'XColor',[1,1,1],... - 'YColor',[1,1,1]); - DATA.GUISettings.VolumeColorGraph=[0.34,0.34,0.34]; - DATA.GUISettings.TimebarAxesColor=[1,1,1]; - DATA.GUISettings.VolumeAxesColor=[1,1,1]; - DATA.AxesTables.volume.fontcolor = [1 1 1]; % [1 1 1];% - DATA.AxesTables.flow.fontcolor = [1 1 1]; - DATA.AxesTables.measurement.fontcolor = [1 1 1]; - DATA.GUISettings.BarColor=[1,0.6,0.2]; %brandgul - foregroundcolor=[1,1,1]; - buttonbackgroundcolor=[0.34,0.34,0.34]; -else - set(DATA.Handles.volumeaxes,'Color',[0,0,0]) - set(DATA.Handles.flowaxes,'Color',[0,0,0]) - set(DATA.Handles.lvuipanel,'HighlightColor',[0,0,0]) - set(DATA.Handles.flowuipanel,'HighlightColor',[0,0,0]) - set(DATA.Handles.measurementuipanel,'HighlightColor',[0,0,0]) - DATA.GUISettings.VolumeAxesColor=[0,0,0]; - set(DATA.Handles.timebaraxes,'Color',[1,1,1]) - set(DATA.Handles.timebaraxes,... - 'XColor',[0,0,0],... - 'YColor',[0,0,0]); - DATA.GUISettings.TimebarAxesColor=[0,0,0]; - DATA.GUISettings.VolumeColorGraph=[1,1,1]; - DATA.GUISettings.BarColor=DATA.GUISettings.BarColorDefault; - DATA.AxesTables.volume.fontcolor = [0 0 0]; % [1 1 1];% - DATA.AxesTables.flow.fontcolor = [0 0 0]; - DATA.AxesTables.measurement.fontcolor = [0 0 0]; - foregroundcolor=[0,0,0]; - buttonbackgroundcolor=backgroundcolor; -end - -DATA.updateflowaxes; -DATA.updatevolumeaxes; -if ~isempty(SET) - DATA.updatetimebaraxes; -end - -if ~strcmp(DATA.ProgramName,'Segment') - set(DATA.Handles.lvstackpushbutton,'BackgroundColor',buttonbackgroundcolor,'foregroundcolor',foregroundcolor) - set(DATA.Handles.rvstackpushbutton,'BackgroundColor',buttonbackgroundcolor,'foregroundcolor',foregroundcolor) - set(DATA.Handles.flowstackpushbutton,'BackgroundColor',buttonbackgroundcolor,'foregroundcolor',foregroundcolor) -end - -set(DATA.Handles.slider1text,'ForegroundColor',foregroundcolor) -set(DATA.Handles.slider2text,'ForegroundColor',foregroundcolor) - set(DATA.Handles.thumbnailslider,'backgroundcolor',slidercolor); - -%LV and RV report table -DATA.AxesTables.volume.backgroundcolor = backgroundcolor;%[0.94 0.94 0.94]; %[0 0 0];% -DATA.AxesTables.flow.backgroundcolor = backgroundcolor;%[0.94 0.94 0.94]; %[0 0 0];% -DATA.AxesTables.measurement.backgroundcolor = backgroundcolor;%[0.94 0.94 0.94]; %[0 0 0];% - -DATA.AxesTables.volume.draw -DATA.AxesTables.flow.draw -DATA.AxesTables.measurement.draw - -% setinterfacecolor(DATA.fig); - -%------------------------ -function default_Callback %#ok -%------------------------ -%Sets default preferences called from GUI -global DATA - -DATA.defaultpref; -update; - -%--------------------- -function save_Callback(silent) -%--------------------- -%Save preferences to disk -% -%When changing in this function also make the same changes in -%loadpreferences/savetodisk function. - -if nargin < 1 - silent = false; -end - -global DATA - -pathname = getpreferencespath; -pathnamesaveall = pwd; %Segment folder -Pref = DATA.Pref; %#ok %Saved to file -%check if preferences for all users already exist -if exist([pathnamesaveall filesep 'default_preferences.mat'],'file') %,'Pref', DATA.Pref.SaveVersion); - if not(silent) - myfailed('Default preferences for all users exists and thereby used prior to local preferences.',DATA.GUI.Segment); - - %lägg till att läsa default preferences och skriva över lokala. - %Uppdatera gui. - end -end - -try - save([pathname filesep '.segment_preferences.mat'],'Pref', DATA.Pref.SaveVersion); -catch %#ok - myfailed('Could not save preferences. Write permission? Disk full?',DATA.PrefHandles.fig); - return; -end; - -disp('Preferences saved.'); - -%--------------------------- -function savetoall_Callback %#ok -%--------------------------- -%Save preferences for all users. Saves to the file defaul_preferences.mat. -%If this file exists, then the PACS and Server settings are copied (and -%overwritten) for the user upon loading. - -global DATA - -%Display message about potentially require admin rights. -adminrequirement - -Pref = DATA.Pref; %#ok %Saved to file - -pathname = pwd; -try - save([pathname filesep 'default_preferences.mat'],'Pref', DATA.Pref.SaveVersion); - disp('Preferences saved to all users (file default preferences).'); -catch - myfailed('Could not save preferences. Write permission? Disk full?',DATA.PrefHandles.fig); -end; - -%-------------------------------- -function closepushbutton_Callback %#ok -%-------------------------------- -global DATA - -close(DATA.PrefHandles.fig); -DATA.PrefHandles = []; - -if DATA.DataLoaded - segment('viewinterp_Callback',DATA.Pref.ViewInterpolated); - segment('thumbnailslider_Callback'); - drawfunctions('drawthumbnails'); - segment('viewrefreshall_Callback'); - -end - -%--------------------------- -function datapath_Callback %#ok -%--------------------------- -global DATA - -if exist(DATA.Pref.datapath,'dir') - temp = myuigetdir(DATA.Pref.datapath,'Select folder for data'); -else - temp = myuigetdir(pwd,'Select folder for data'); -end; -if ~(isempty(temp)||isequal(temp,0)) - DATA.Pref.datapath = temp; - DATA.Preview.PathName = temp; -end; - -update; - -%--------------------------- -function exportpath_Callback %#ok -%--------------------------- -global DATA - -if exist(DATA.Pref.exportpath,'dir') - temp = myuigetdir(DATA.Pref.exportpath,'Select folder for exporting'); -else - temp = myuigetdir(pwd,'Select folder for exporting'); -end; - -if ~(isempty(temp)||isequal(temp,0)) - DATA.Pref.exportpath = temp; -end; - -update; - -%----------------------- -function cdpath_Callback %#ok -%----------------------- -global DATA - -temp = myuigetdir(pwd,'Select drive letter for CD or mount location:'); - -if ~(isempty(temp)||isequal(temp,0)) - DATA.Pref.CDPath = temp; -else - myfailed('Aborted.',DATA.PrefHandles.fig); -end - -update; - - -%------------------------------------- -function gpu_Callback %#ok -%------------------------------------- -global DATA - -val = get(DATA.PrefHandles.gpucheckbox,'Value'); -if val == 0 - disp('GPU acceleration disabled.'); - mymsgbox('GPU acceleration disabled.'); - DATA.Pref.GPU.NumGPU = 0; - DATA.Pref.GPU.Use = false; -else - DATA.Pref.GPU.NumGPU = gpuDeviceCount; - if DATA.Pref.GPU.NumGPU > 0 - DATA.Pref.GPU.Use = true; - disp('GPU acceleration enabled.'); - mymsgbox('GPU acceleration enabled.'); - else - DATA.Pref.GPU.Use = false; - set(DATA.PrefHandles.gpucheckbox,'Value',false); - myfailed('Could not detect any GPU on this computer.'); - end; - -end - -%------------------------------------- -function openGL_Callback %#ok -%------------------------------------- - -global DATA - -val = get(DATA.PrefHandles.openGLcheckbox,'Value'); -if val == 0 - disp('Selecting hardware openGL.'); - opengl hardware -else - disp('Selecting software openGL.'); - opengl software -end - -%Write to log-file -opengl info - -DATA.Pref.OpenGLSoftware = val; - -update; - -%--------------------------- -function tempfolder_Callback -%--------------------------- -%Sets temporaryfolder used by Segment Server and PACS connection (subfolder tempsearch) - -global DATA - -if ~isempty(DATA.Pref.Pacs.ImageBasePath) - if isdir([DATA.Pref.Pacs.ImageBasePath filesep 'TEMP']) - suggestedfolder = [DATA.Pref.Pacs.ImageBasePath filesep 'TEMP']; - else - suggestedfolder = DATA.Pref.Pacs.ImageBasePath; - end -else - suggestedfolder = pwd; -end -folder = myuigetdir(suggestedfolder,'Select folder for temporary storage for patient database and PACS connection. Recommended to keep on SSD disc'); - -DATA.Pref.Pacs.TempStoragePath = folder; - -updateadvanced; - -%------------------------------------- -function imagebasepath_Callback(folder) %#ok -%------------------------------------- -%Set folder for patientdatabase. If called with folder then do not ask and -%no update. - -global DATA - -if nargin==0 - if ~isempty(DATA.Pref.Pacs.ImageBasePath) - suggestedfolder = DATA.Pref.Pacs.ImageBasePath; - else - suggestedfolder = pwd; - end - folder = myuigetdir(suggestedfolder,'Select folder for patient database and PACS connection. Recommended to keep on SSD disc'); -end; - -if ~(isempty(folder)||isequal(folder,0)) - - DATA.Pref.Pacs.ImageBasePath = folder; - - %Check if ends with filesep, then remove. This happens when for instance - %selecting root folder, i.e M:\ - if isequal(folder(end),filesep) - folder = folder(1:(end-1)); - end; - - %Assign other folders - DATA.Pref.Pacs.AnalysedPath = [folder filesep 'Analysed']; - DATA.Pref.Pacs.DicomPath = [folder filesep 'DICOM']; - -end; - -if nargin==0 - updateadvanced; -end; - -reportpath_Callback -tempfolder_Callback; - -%------------------------------ -function reportpath_Callback -%------------------------------ -global DATA - -if ~isempty(DATA.Pref.Pacs.ImageBasePath) - suggestedfolder = DATA.Pref.Pacs.ReportsheetPath; -else - suggestedfolder = pwd; -end -temp = myuigetdir(suggestedfolder,'Select base folder for patient reports'); - -if ~(isempty(temp)||isequal(temp,0)) - DATA.Pref.Pacs.ReportsheetPath = temp; -end; - -updateadvanced; - -%------------------------------ -function pafreportpath_Callback %#ok -%------------------------------ -global DATA - -temp = myuigetdir([pwd filesep 'PAF'],'Select base folder for PAF report'); - -if ~(isempty(temp)||isequal(temp,0)) - DATA.Pref.Pacs.PAFPathname = temp; -end; - -updateadvanced; - -%------------------------------- -function copyexportpath_Callback %#ok -%------------------------------- -global DATA - -DATA.Pref.exportpath = DATA.Pref.datapath; - -update; - -%--------------------------------- -function autosavecheckbox_Callback %#ok -%--------------------------------- -global DATA - -DATA.Pref.AutoSave = get(DATA.PrefHandles.autosavecheckbox,'Value'); - -%------------------------------- -function anonymcheckbox_Callback %#ok -%------------------------------- -global DATA - -DATA.Pref.AnonymMode = get(DATA.PrefHandles.anonymcheckbox,'Value'); - -if DATA.Pref.AnonymMode - mymsgbox('This does only blind data when displayed. No changes are made to files.'); -end; - -%-------------------------------------- -function endocenterradiobutton_Callback %#ok -%-------------------------------------- -global DATA - -DATA.Pref.EndoCenter = 1; -set(DATA.PrefHandles.endocenterradiobutton,'Value',1); -set(DATA.PrefHandles.epicenterradiobutton,'Value',0); - -%------------------------------------- -function epicenterradiobutton_Callback %#ok -%------------------------------------- -global DATA - -DATA.Pref.EndoCenter = 0; -set(DATA.PrefHandles.endocenterradiobutton,'Value',0); -set(DATA.PrefHandles.epicenterradiobutton,'Value',1); - -%----------------------------------- -function blackwhitecheckbox_Callback %#ok -%----------------------------------- -global DATA - -DATA.Pref.BlackWhite = get(DATA.PrefHandles.blackwhitecheckbox,'Value'); - -%------------------------------------- -function addpointscheckbox_Callback %#ok -%------------------------------------- -global DATA - -DATA.Pref.AddPoints = get(DATA.PrefHandles.addpointscheckbox,'Value'); - -%------------------------------ -function linewidthedit_Callback %#ok -%------------------------------ -global DATA - -stri = mygetedit(DATA.PrefHandles.linewidthedit); -[linewidth,ok] = str2num(stri); - -if not(ok) - myfailed('Invalid line width.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.linewidthedit,'String',sprintf('%0.5g',DATA.Pref.LineWidth)); - return; -end; - -if linewidth<0.25 - myfailed('Too small line width, minimum 0.25.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.linewidthedit,'String',sprintf('%0.5g',DATA.Pref.LineWidth)); - return; -end; - -if linewidth>5 - myfailed('Too large line width, maximum 5.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.linewidthedit,'String',sprintf('%0.5g',DATA.Pref.LineWidth)); - return; -end; - -%Store & update -DATA.Pref.LineWidth = linewidth; -set(DATA.PrefHandles.linewidthedit,'String',sprintf('%0.5g',DATA.Pref.LineWidth)); - -%------------------------------ -function markersizeedit_Callback %#ok -%------------------------------ -global DATA - -stri = mygetedit(DATA.PrefHandles.markersizeedit); -[markersize,ok] = str2num(stri); - -if not(ok) - myfailed('Invalid marker size.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.markersizeedit,'String',sprintf('%0.5g',DATA.Pref.MarkerSize)); - return; -end; - -if markersize<1 - myfailed('Too small marker size, minimum 1.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.markersizeedit,'String',sprintf('%0.5g',DATA.Pref.MarkerSize)); - return; -end; - -if markersize>20 - myfailed('Too large marker size, maximum 20.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.markersizeedit,'String',sprintf('%0.5g',DATA.Pref.MarkerSize)); - return; -end; - -%Store & update -DATA.Pref.MarkerSize = markersize; -set(DATA.PrefHandles.markersizeedit,'String',sprintf('%0.5g',DATA.Pref.MarkerSize)); - -%------------------------------ -function numberthumbnailsedit_Callback %#ok -%------------------------------ -global DATA - -stri = mygetedit(DATA.PrefHandles.numberthumbnailsedit); -[numberthumbnails,ok] = str2num(stri); - -if not(ok) - myfailed('Invalid number of thumbnails.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.numberthumbnailsedit,'String',sprintf('%0.5g',DATA.Pref.NumberVisibleThumbnails)); - return; -end; - -if numberthumbnails<1 - myfailed('At least one thumbnail must be visible.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.numberthumbnailsedit,'String',sprintf('%0.5g',DATA.Pref.NumberVisibleThumbnails)); - return; -end; - -if numberthumbnails>20 - myfailed('A maximum of 20 thumbnails can be visible.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.numberthumbnailsedit,'String',sprintf('%0.5g',DATA.Pref.NumberVisibleThumbnails)); - return; -end; - -%Store & update -DATA.Pref.NumberVisibleThumbnails = numberthumbnails; -set(DATA.PrefHandles.numberthumbnailsedit,'String',sprintf('%0.5g',DATA.Pref.NumberVisibleThumbnails)); - -%----------------------------------- -function radialprofilesedit_Callback %#ok -%----------------------------------- -global DATA - -stri = mygetedit(DATA.PrefHandles.radialprofilesedit); - -[radialprofiles,ok] = str2num(stri); -if not(ok) - myfailed('Invalid number of points.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.radialprofilesedit,'String',sprintf('%d',DATA.Pref.RadialProfiles)); - return; -end; - -radialprofiles = round(radialprofiles); - -if radialprofiles<80 - myfailed('Can not be smaller than 80.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.radialprofilesedit,'String',sprintf('%d',DATA.Pref.RadialProfiles)); - return; -end; - -if radialprofiles>1000 - myfailed('Can not be larger than 1000.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.radialprofilesedit,'String',sprintf('%d',DATA.Pref.RadialProfiles)); - return; -end; - -%Store & update -DATA.Pref.RadialProfiles = radialprofiles; -set(DATA.PrefHandles.radialprofilesedit,'String',sprintf('%d',DATA.Pref.RadialProfiles)); - -%--------------------------------- -function interppointsedit_Callback %#ok -%--------------------------------- -global DATA - -stri = mygetedit(DATA.PrefHandles.interppointsedit); - -[interppoints,ok] = str2num(stri); -if not(ok) - myfailed('Invalid number of points.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.interppointsedit,'String',sprintf('%d',DATA.Pref.NumInterpPoints)); - return; -end; - -interppoints = round(interppoints); -DATA.Pref.NumInterpPoints = interppoints; -set(DATA.PrefHandles.interppointsedit,'String',sprintf('%d',DATA.Pref.NumInterpPoints)); - -%------------------------------ -function numpointsedit_Callback %#ok -%------------------------------ -global DATA SET - -stri = mygetedit(DATA.PrefHandles.numpointsedit); - -[numpoints,ok] = str2num(stri); -if not(ok) - myfailed('Invalid number of points.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.numpointsedit,'String',sprintf('%d',DATA.Pref.NumPoints)); - return; -end; - -numpoints = round(numpoints); - -if numpoints<80 - myfailed('Can not be smaller than 80.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.numpointsedit,'String',sprintf('%d',DATA.Pref.NumPoints)); - return; -end; - -if numpoints>1000 - myfailed('Can not be larger than 1000.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.numpointsedit,'String',sprintf('%d',DATA.Pref.NumPoints)); - return; -end; -%Store & update -DATA.Pref.NumPoints = numpoints; -set(DATA.PrefHandles.numpointsedit,'String',sprintf('%d',DATA.Pref.NumPoints)); -DATA.NumPoints = DATA.Pref.NumPoints; -set(DATA.PrefHandles.numpointstext,'String',sprintf('%d',DATA.NumPoints)); -h = mywaitbarstart(length(SET),'Please wait, resampling curves.'); - -for loop=1:length(SET) - numpointsedithelper(loop); - segment('updatemodeldisplay',loop); - h = mywaitbarupdate(h); -end; -mywaitbarclose(h); - -%--------------------------- -function numpointsedithelper(loop) -%--------------------------- -global DATA SET - -if ~isempty(SET(loop).EndoX) - [SET(loop).EndoX,SET(loop).EndoY] = calcfunctions('resamplemodel',... - SET(loop).EndoX,SET(loop).EndoY,DATA.NumPoints); -end; -if ~isempty(SET(loop).EpiX) - [SET(loop).EpiX,SET(loop).EpiY] = calcfunctions('resamplemodel',... - SET(loop).EpiX,SET(loop).EpiY,DATA.NumPoints); -end; -if ~isempty(SET(loop).RVEndoX) - [SET(loop).RVEndoX,SET(loop).RVEndoY] = calcfunctions('resamplemodel',... - SET(loop).RVEndoX,SET(loop).RVEndoY,DATA.NumPoints); -end; -if ~isempty(SET(loop).RVEpiX) - [SET(loop).RVEpiX,SET(loop).RVEpiY] = calcfunctions('resamplemodel',... - SET(loop).RVEpiX,SET(loop).RVEpiY,DATA.NumPoints); -end; -for rloop=1:SET(loop).RoiN - [SET(loop).Roi(rloop).X,SET(loop).Roi(rloop).Y] = calcfunctions('resamplemodel',... - SET(loop).Roi(rloop).X,SET(loop).Roi(rloop).Y,DATA.NumPoints); -end - -% if isopengui('strain.fig') -% mywarning('Strain analysis needs to be redone after changing Number of points along contour. Closing Strain GUI.') -% straintagging.straintagging('close_Callback') -% end - -%------------------------------------------ -function contouradjustdistanceedit_Callback %#ok -%------------------------------------------ -global DATA - -stri = mygetedit(DATA.PrefHandles.contouradjustdistanceedit); - -[dist,ok] = str2num(stri); -if not(ok) - myfailed('Invalid distance.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.contouradjustdistanceedit,'String',... - sprintf('%0.5g',DATA.Pref.ContourAdjustDistance)); - return; -end; - -if dist<0 - myfailed('Distance may not be negative.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.contouradjustdistanceedit,'String',... - sprintf('%0.5g',DATA.Pref.ContourAdjustDistance)); - return; -end; - -if dist>40 - myfailed('Too large distance, max 40.',DATA.PrefHandles.fig); - set(DATA.PrefHandles.contouradjustdistanceedit,'String',... - sprintf('%0.5g',DATA.Pref.ContourAdjustDistance)); - return; -end - -DATA.Pref.ContourAdjustDistance = dist; -set(DATA.PrefHandles.contouradjustdistanceedit,'String',... - sprintf('%0.5g',DATA.Pref.ContourAdjustDistance)); - -%--------------------------------------- -function includeallpixelsinroi_Callback %#ok -%--------------------------------------- -global DATA - -DATA.Pref.IncludeAllPixelsInRoi = get(DATA.PrefHandles.includeallpixelsinroicheckbox,'Value'); - -%------------------------- -function donotask_Callback %#ok -%------------------------- -global DATA - -DATA.Pref.DoNotAsk = get(DATA.PrefHandles.donotaskcheckbox,'value'); - -%------------------------------ -function dicomportedit_Callback %#ok -%------------------------------ -global DATA - -temp = mygetedit(DATA.PrefHandlesAdvanced.dicomportedit); -temp = removechars(temp); - -DATA.Pref.Server.DICOMPort = temp; -set(DATA.PrefHandlesAdvanced.dicomportedit,'string',temp); - -%---------------------------- -function aetitleedit_Callback %#ok -%---------------------------- -global DATA - -temp = mygetedit(DATA.PrefHandlesAdvanced.aetitleedit); -temp = upper(temp); - -DATA.Pref.Server.AETitle = temp; -set(DATA.PrefHandlesAdvanced.aetitleedit,'string',temp); - -%----------------------------------- -function receiveoptionsedit_Callback %#ok -%----------------------------------- -global DATA -stri = mygetedit(DATA.PrefHandlesAdvanced.receiveoptionsedit); -DATA.Pref.Server.ReceiveOptions = stri; - -%-------------------------------- -function sendoptionsedit_Callback %#ok -%-------------------------------- -global DATA -stri = mygetedit(DATA.PrefHandlesAdvanced.sendoptionsedit); -DATA.Pref.Pacs.SendOptions = stri; - -%--------------------------- -function switchtags_Callback -%--------------------------- -global DATA -DATA.Pref.Pacs.SwitchTags = mygetvalue(DATA.PrefHandlesAdvanced.switchtagscheckbox); - -%---------------------------------- -function normalizephaseask_Callback %#ok -%---------------------------------- -global DATA -DATA.Pref.Dicom.NormalizePhase=[]; -DATA.normalizephaseupdate; - -%---------------------------------- -function normalizephaseyes_Callback %#ok -%---------------------------------- -global DATA -DATA.Pref.Dicom.NormalizePhase=1; -DATA.normalizephaseupdate; - -%--------------------------------- -function normalizephaseno_Callback %#ok -%--------------------------------- -global DATA -DATA.Pref.Dicom.NormalizePhase=0; -DATA.normalizephaseupdate; - -%-------------------------------------- -function uselightcontrast_Callback %#ok -%-------------------------------------- -global DATA -DATA.BalloonLevel = -1; %will force recalc of balloon image. -%DATA.UseLight = get(DATA.PrefHandles.uselightcheckbox,'value'); -DATA.Pref.UseLight = get(DATA.PrefHandles.uselightcheckbox,'value'); - -%---------------------------------- -function viewinterpolated_Callback %#ok -%---------------------------------- -global DATA - -DATA.Pref.ViewInterpolated = get(DATA.PrefHandles.viewinterpolatedcheckbox,'value'); -if ~DATA.Pref.ViewInterpolated - DATA.Handles.permanenticonholder.indent('viewpixels',0) -else - DATA.Handles.permanenticonholder.undent('viewpixels',0) -end - -%---------------------------------- -function bgcolor_Callback %#ok -%---------------------------------- -global DATA - -DATA.Pref.BackgroundColor = get(DATA.PrefHandles.bgcolorcheckbox,'value'); - -%---------------------------------- -function force16bit_Callback %#ok -%---------------------------------- -global DATA -DATA.Pref.Dicom.Force16Bit = get(DATA.PrefHandlesAdvanced.force16bitcheckbox,'value'); - -%------------------------------- -function fasterpreview_Callback %#ok Callback from segpref.fig -%------------------------------- -global DATA -DATA.Pref.Dicom.FasterPreview = get(DATA.PrefHandlesAdvanced.fasterpreviewcheckbox,'value'); - -%------------------------------- -function showseriesdescription_Callback %#ok Callback from segpref.fig -%------------------------------- -global DATA -DATA.Pref.ShowSeriesDescription = ... - get(DATA.PrefHandles.showseriesdescriptioncheckbox, 'value'); - -%------------------------------- -function hidefilesunix_Callback %#ok Callback from segpref.fig -%------------------------------- -global DATA -DATA.Pref.HideFilesUnix =get(DATA.PrefHandles.hidefilesunixcheckbox, 'value'); - -%---------------------------------------- -function fastpreviewloadcheckbox_Callback %#ok Callback from segpref.fig -%---------------------------------------- -global DATA -DATA.Pref.FastPreviewLoad = get(DATA.PrefHandles.fastpreviewloadcheckbox,'value'); - -%------------------------------------- -function checkversioncheckbox_Callback %#ok -%------------------------------------- -global DATA -DATA.Pref.CheckVersion = get(DATA.PrefHandles.checkversioncheckbox,'value'); - -%-------------------------------- -function testproxyserver_Callback %#ok -%-------------------------------- -try - stri = urlread('http://www.google.com'); - if isempty(stri) - error('ERROR:SEGMENT','Google page seems to be empty.'); - end; - if nargout == 0 - mymsgbox('Successfull: Could connect to Internet.'); - end; -catch me - stri = sprintf([... - 'Could not connect to Internet.\n\n' ... - 'Please try your normal web browser. ' ... - 'If your normal web browser work, then ' ... - 'the most probable cause is HTTP proxy server. ' ... - 'Please contact your system administrator to get ' ... - 'details of find out more about your local configuration. ' ... - 'Thereafter, please contact support@medviso.com to get a solution.']); - myfailed(stri); - mydispexception(me); -end - -%------------------------------------- -function useproxyserver_Callback(value) -%------------------------------------- -global DATA - -if nargin==0 - value = get(DATA.PrefHandles.useproxyservercheckbox,'value'); -end; - -DATA.Pref.UseProxyServer = value; -set(DATA.PrefHandles.useproxyservercheckbox,'value',value); - -%Check if not properly defined -if DATA.Pref.UseProxyServer - if isequal(DATA.Pref.ProxySettings.HostName,'') - myfailed('No proxy server configured. Aborted.'); - defineproxyserver_Callback; - DATA.Pref.UseProxyServer = false; - set(DATA.PrefHandles.useproxyservercheckbox,'value',0); - end; -end; - -if ~DATA.Pref.UseProxyServer - disp('No proxy server used'); -end; - -useproxyserver(DATA.Pref.UseProxyServer); - -%---------------------------------- -function defineproxyserver_Callback -%---------------------------------- -global DATA - -prompt = {... - 'HostName',... - 'Port',... - 'UserName',... - 'Password'}; - -% def = {... -% DATA.Pref.ProxySettings.HostName ... -% DATA.Pref.ProxySettings.Port ... -% DATA.Pref.ProxySettings.UserName ... -% DATA.Pref.ProxySettings.Password}; -def = {... - DATA.Pref.ProxySettings.HostName ... - DATA.Pref.ProxySettings.Port ... - DATA.Pref.ProxySettings.UserName ... - ''}; - -res = inputdlg(prompt,'Enter data',1,def); - -if not(length(res)==length(prompt)) - myfailed('Aborted.'); - return; -end; - -DATA.Pref.ProxySettings.HostName = res{1}; -DATA.Pref.ProxySettings.Port = res{2}; -DATA.Pref.ProxySettings.UserName = res{3}; -DATA.Pref.ProxySettings.Password = res{4}; - -if isequal(DATA.Pref.ProxySettings.HostName,'') || isempty(DATA.Pref.ProxySettings.HostName) - disp('No proxy server used'); - useproxyserver_Callback(false); -else - useproxyserver_Callback(true); -end; - -%----------------------------------- -function language_Callback(language) %#ok -%----------------------------------- -global DATA - -if isfield(DATA.Handles,'englishmenu') - set(DATA.Handles.englishmenu,'Checked','off'); -end -if isfield(DATA.Handles,'svenskamenu') - set(DATA.Handles.svenskamenu,'Checked','off'); -end -% if isfield(DATA.Handles,'italianomenu') -% set(DATA.Handles.italianomenu,'Checked','off'); -% end -if isfield(DATA.Handles,'deutschmenu') - set(DATA.Handles.deutschmenu,'Checked','off'); -end -% set([DATA.Handles.englishmenu DATA.Handles.svenskamenu DATA.Handles.italianomenu DATA.Handles.deutschmenu],'Checked','off'); -try - eval(sprintf('set(DATA.Handles.%smenu,''Checked'',''on'')',lower(language))); -catch % if the current language does not exist in the current software - DATA.Pref.Language = 'English'; - language = 'English'; - eval(sprintf('set(DATA.Handles.%smenu,''Checked'',''on'')',lower(language))); -end -prevlanguage = DATA.Pref.Language; -DATA.Pref.Language = language; -if strcmp(prevlanguage,language) - prevlanguage = 'English'; -end - -if isfield(DATA.Handles,'toggleiconholder'); - DATA.setribbonimages(language); -end -set(get(DATA.Handles.volumeaxes,'xlabel'),'string',translation.dictionary(... - 'Time [ms]'))%get(get(DATA.Handles.volumeaxes,'xlabel'),'string'))) -set(get(DATA.Handles.volumeaxes,'ylabel'),'string',translation.dictionary(... - 'Volume [ml]'))%get(get(DATA.Handles.volumeaxes,'ylabel'),'string'))) -set(get(DATA.Handles.flowaxes,'xlabel'),'string',translation.dictionary(... - 'Time [ms]'))%get(get(DATA.Handles.flowaxes,'xlabel'),'string'))) -set(get(DATA.Handles.flowaxes,'ylabel'),'string',translation.dictionary(... - 'Flow [ml/s]'))%get(get(DATA.Handles.flowaxes,'ylabel'),'string'))) -set(get(DATA.Handles.timebaraxes,'xlabel'),'string',translation.dictionary(... - 'Time [ms]'))%get(get(DATA.Handles.timebaraxes,'xlabel'),'string'))) -% set(DATA.Handles.lvstackpushbutton,'String',dprintf('Stack #%d',no)); -if isfield(DATA.Handles,'lvstackpushbutton') - if ~isempty(DATA.LVNO) - set(DATA.Handles.lvstackpushbutton,'String',dprintf(translation.dictionary('Stack #%d'),DATA.LVNO)); - else - set(DATA.Handles.lvstackpushbutton,'String',dprintf(translation.dictionary('Set stack'))); - end -end -if isfield(DATA.Handles,'rvstackpushbutton') - if ~isempty(DATA.RVNO) - set(DATA.Handles.rvstackpushbutton,'String',dprintf(translation.dictionary('Stack #%d'),DATA.RVNO)); - else - set(DATA.Handles.rvstackpushbutton,'String',dprintf(translation.dictionary('Set stack'))); - end -end -if isfield(DATA.Handles,'flowstackpushbutton') - if ~isempty(DATA.FlowNO) - set(DATA.Handles.flowstackpushbutton,'String',dprintf(translation.dictionary('Stack #%d'),DATA.FlowNO)); - else - set(DATA.Handles.flowstackpushbutton,'String',dprintf(translation.dictionary('Set stack'))); - end -end - - -%DATA.flowreportupdate -if isfield(DATA.AxesTables,'flow') -DATA.AxesTables.flow.draw(); -%DATA.AxesTables.flow.updateName('Backward','Backward',true); -%DATA.AxesTables.flow.updateName('Forward','Forward',true); -%DATA.AxesTables.flow.updateTitle('Flow',true); -end - -guis = fieldnames(DATA.GUI); -for i = 1:numel(guis) - if isa(DATA.GUI.(guis{i}),'mygui') - translation.translatealllabels(DATA.GUI.(guis{i}).fig,prevlanguage); - end -end -silent = true; -save_Callback(silent); %Always save, silent true - -%----------------------------------- -function askaddcommentcheckbox_Callback -%----------------------------------- -%Callback for define if asking for add comment to patient database - -global DATA - -DATA.Pref.AskAddComment = get(DATA.PrefHandles.checkboxaskaddcomment,'value'); - - -%--------------------------- -function webbrowser_Callback %#ok Callback from segpref.fig -%--------------------------- -global DATA - -chosenwebbrowser=get(DATA.PrefHandles.webbrowserpopupmenu,'value'); - -browserexist=false; -browser='explorer'; -browserpath='internal command'; -switch chosenwebbrowser - case 1 - if ispc - browserexist=true; - DATA.Pref.WebBrowser='explorer'; - end - case 2 - browser = 'Mozilla Firefox\firefox.exe'; - browserpath = getenv('ProgramFiles'); - browserexist=exist([browserpath filesep 'Mozilla Firefox'],'dir'); - if browserexist - browserexist=exist([browserpath filesep 'Mozilla Firefox' filesep 'firefox.exe'],'file'); - if browserexist - DATA.Pref.WebBrowser=[browserpath filesep browser]; - end - end - case 3 - browserpath = getenv('ProgramFiles'); - browser = 'other'; - [filename,pathname] = myuigetfile('*.*','Select web browser to use',browserpath); - if (pathname~=0) - browserexist=true; - DATA.Pref.WebBrowser=[pathname filename]; - end -end -if not(browserexist) - myfailed(dprintf('Web browser %s does not exist in %s. Choose another web browser.',browser, browserpath)); -end - - -%---------------------------------- -function advancedsettings_Callback %#ok called from segpref.fig -%---------------------------------- - -global DATA - -fig = openfig('segprefadvanced.fig','reuse'); -set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); %DATA.GUISettings.BackgroundColor); % -translation.translatealllabels(fig); - -% Generate a structure of handles to pass to callbacks, and store it. -DATA.PrefHandlesAdvanced = guihandles(fig); -DATA.PrefHandlesAdvanced.fig = fig; - -updateadvanced; - -%---------------------- -function updateadvanced -%---------------------- -global DATA - -DATA.updateprefhandlesadvanced; - -%-------------------------------- -function defaultadvanced_Callback %#ok called from segprefadvanced.fig -%-------------------------------- -global DATA - -%DICOM Communication Settings -DATA.Pref.Pacs.ImageBasePath = [pwd filesep 'Database']; -DATA.Pref.Pacs.TempStoragePath = [pwd filesep 'Database' filesep 'TempStorage']; -DATA.Pref.Pacs.DicomPath = [pwd filesep 'Database' filesep 'DICOM']; -DATA.Pref.Pacs.AnalysedPath = [pwd filesep 'Database' filesep 'Analysed']; -DATA.Pref.Pacs.ReportsheetPath = [pwd filesep 'Database' filesep 'Report']; -DATA.Pref.Server.DICOMPort = '104'; -aetitle = getenv('COMPUTERNAME'); -if isempty(aetitle) - aetitle = 'SEGMENT'; -end; -DATA.Pref.Server.AETitle = aetitle; - -%DICOM interpretation -DATA.Pref.Dicom.FasterPreview = true; -DATA.Pref.Dicom.Force16Bit = false; -DATA.Pref.Dicom.NormalizePhase = []; - -DATA.Pref.Server.ReceiveOptions = ''; -DATA.Pref.Pacs.SendOptions = ''; - -updateadvanced; - -%-------------------------------- -function closeadvancedpushbutton_Callback %#ok %called from segprefadvanced.fig -%-------------------------------- -global DATA - -close(DATA.PrefHandlesAdvanced.fig); -DATA.PrefHandlesAdvanced = []; - -%-------------------------------- -function generatebatfile_Callback %#ok -%-------------------------------- -%Function to generate .bat files for server and sorter - -global DATA - -if ~checkdatabaselicense - return; -end; - -adminrequirement; %message that it may require admin rights. - -segmentpath = pwd; - -%Create path for logfile if it does not already -logfilepath = [DATA.Pref.Pacs.TempStoragePath filesep 'logfiles']; -sucess = mymkdir(logfilepath); -if ~sucess - myfailed('Could not create folder for logfile. Check write permission.'); - return; -end; - -%--- Prepare data for bat file -if ispc - callname = 'storescp.exe'; -else - callname = 'storescp'; -end; -outpath = DATA.Pref.Pacs.TempStoragePath; -dicomport = DATA.Pref.Server.DICOMPort; -aetitle = DATA.Pref.Server.AETitle; -receiveoptions = DATA.Pref.Server.ReceiveOptions; - -%--- Create the segment storage server file -[fid, message] = fopen('segmentstorageserver.bat','wt'); - -%Check if could create. -if fid<0 - myfailed(sprintf('Could not create file. Detailed message:%s',message)) - return; -end; - -%Create string & write -fprintf(fid,'"%s%s%s" -od "%s" %s -aet "%s" %s \n',... - segmentpath,... %path to executable, this is segmentpath - filesep,... %filesep - callname,... %name of executable - outpath,... %pathname for output directory (temporary directory) - receiveoptions,... %receiveoptions - aetitle,... %aetitle - dicomport); %port name - -%Close the file -fclose(fid); - -%--- Create the segmentsorterbatfile - -%Create the segment storage server file -[fid, message] = fopen('segmentsorterserver.bat','wt'); - -%Check if could create. -if fid<0 - myfailed(sprintf('Could not create file. Detailed message:%s',message)) - return; -end; - -%Create string & write -if ispc - callname = 'segmentserversorter.exe'; -else - callname = 'segmentserversorter'; -end; -databasepath = DATA.Pref.Pacs.ImageBasePath; - -%segmentserversorter(DATA.Pref.Pacs.TempStoragePath, DATA.Pref.Pacs.ImageBasePath); - -fprintf(fid,'"%s%s%s" "%s" "%s" \n',... - segmentpath,... %path to executable, this is segmentpath - filesep,... %filesep - callname,... %name of executable - outpath,... %pathname for output directory (temporary directory) - databasepath); - -%Close the file -fclose(fid); - -mymsgbox('Created storage and sorter .bat files.'); - -%------------------------------- -function installservices_Callback %#ok -%------------------------------- -%Install the segmentstorageserver & segmentsorterservice as services. - -if ~checkdatabaselicense - return; -end; -forbidden={'segmentserversorter.exe', 'nssm.exe', 'storescu.exe'}; - -isrunning=zeros(size(forbidden)); - -for i=length(forbidden) - [~,result] = system(sprintf('tasklist /FI "imagename eq %s" /fo table /nh',forbidden{i})); - if ~isempty(regexp(lower(result),forbidden{i}, 'once'))%strcmp(lower(result(1:length(forbidden{i}))),forbidden{i}) - isrunning(i)=1; - end -end - -if any(isrunning) - answer=yesno(sprintf('To proceed with install, the following services need to shutdown:\n\n%s\n%s\n\n Do this now?','SegmentStorageServer' , 'SegmentSorterService')); - if answer - segpref('editservices_Callback') - else - return - end -end - -segmentpath = pwd; - -%--- StorageServer -storagebatfilename = [pwd filesep 'segmentstorageserver.bat']; - -if ~exist(storagebatfilename,'file') - myfailed('No storage .bat file exist, please generate.'); - return; -end; - -stri = sprintf('"%s%snssm.exe" install SegmentStorageServer "%s"',... - segmentpath,... - filesep,... - storagebatfilename); - -[status,result] = system(stri); -statushelper('install service',status,result); -if isequal(status,0) - mymsgbox('SegmentStorageServer service have been installed. It is not yet running. Either start manually (under Edit), or restart computer.'); -end; - -%--- SorterServer -sorterbatfilename = [pwd filesep 'segmentsorterserver.bat']; - -if ~exist(sorterbatfilename,'file') - myfailed('No sorter .bat file exist, please generate.'); - return; -end; - -stri = sprintf('"%s%snssm.exe" install SegmentSorterServer "%s"',... - segmentpath,... - filesep,... - sorterbatfilename); - -[status,result] = system(stri); -statushelper('install service',status,result); -if isequal(status,0) - mymsgbox('SegmentSorterServer service have been installed. It is not yet running. Either start manually (under Edit), or restart computer.'); -end; - -% %isrunning=wasrunning -% if any(isrunning) -% try -% tostart=find(isrunning); -% %To start and stop you need administrator priviliges, is pause sufficient? -% for i=tostart -% [~,result] = system(sprintf('net start %s',forbidden{isrunning(i)})); -% end -% catch -% mywarning('Failed to start previously ongoing process, are administrator priviliges on?') -% return; -% end -% end - -%-------------------------------- -function deletestorageservice_Callback %#ok -%-------------------------------- -%Delete SegmentStorageServer as service. - -if ~checkdatabaselicense - return; -end; - -mymsgbox('Make sure that the SegmentStorageServer is stopped before deleting.'); - -segmentpath = pwd; - -%StorageService -stri = sprintf('"%s%snssm.exe" remove SegmentStorageServer',... - segmentpath,... - filesep); -[status,result] = system(stri); -statushelper('remove service',status,result); - -%-------------------------------- -function deletesorterservice_Callback %#ok -%-------------------------------- -%Delete SegmentSorterServer as service. - -if ~checkdatabaselicense - return; -end; - -mymsgbox('Make sure that the SegmentSorterServer is stopped before deleting.'); - -segmentpath = pwd; - -%SorterService -stri = sprintf('"%s%snssm.exe" remove SegmentSorterServer',... - segmentpath,... - filesep); -[status,result] = system(stri); -statushelper('remove service',status,result); - -%----------------------------- -function editservices_Callback %#ok -%----------------------------- -%Starts system editor for services. - -if ~checkdatabaselicense - return; -end; - -mymsgbox('Stop/Start SegmentStorageServer and SegmentSorterService. Segment will not be responsive before you close services editor. Now starting services.msc.'); -system('services.msc'); -mymsgbox('Services editor closed.'); - - -%----------------------------------- -function statushelper(stri,status,result) -%----------------------------------- -%Helper function to generate error messages - -if ~isequal(status,0) - myfailed(sprintf('Could not %s. Message:%s',stri,result)); -end; - -%------------------------------------ -function ok = checkdatabaselicense -%------------------------------------ -global DATA - -ok = false; - -if not(isequal(3,getmodule(2,'D',[],true))) %'' => make license check silent. - myfailed('Your license does not include this module.',DATA.GUI.Segment); - return; -end; - -ok = true; \ No newline at end of file diff --git a/source/segpref.p b/source/segpref.p new file mode 100644 index 0000000..2470a38 Binary files /dev/null and b/source/segpref.p differ diff --git a/source/segprefadvanced.fig b/source/segprefadvanced.fig index 09beb96..d23376e 100644 Binary files a/source/segprefadvanced.fig and b/source/segprefadvanced.fig differ diff --git a/source/segrawstack.p b/source/segrawstack.p index 01c7b7d..88e7b78 100644 Binary files a/source/segrawstack.p and b/source/segrawstack.p differ diff --git a/source/sendDICOMfile.p b/source/sendDICOMfile.p index c7cd833..9fd4c68 100644 Binary files a/source/sendDICOMfile.p and b/source/sendDICOMfile.p differ diff --git a/source/sendfiles.fig b/source/sendfiles.fig index ce1ba8e..929b9d7 100644 Binary files a/source/sendfiles.fig and b/source/sendfiles.fig differ diff --git a/source/septalvolume.fig b/source/septalvolume.fig index a1716cc..5186045 100644 Binary files a/source/septalvolume.fig and b/source/septalvolume.fig differ diff --git a/source/seriesselector.fig b/source/seriesselector.fig index 8e73e91..b3f16d7 100644 Binary files a/source/seriesselector.fig and b/source/seriesselector.fig differ diff --git a/source/seriesselector.p b/source/seriesselector.p index 6d37145..db34870 100644 Binary files a/source/seriesselector.p and b/source/seriesselector.p differ diff --git a/source/setinterfacecolor.m b/source/setinterfacecolor.m new file mode 100644 index 0000000..42e317c --- /dev/null +++ b/source/setinterfacecolor.m @@ -0,0 +1,151 @@ +function setinterfacecolor(handle) +%set background color and text color for all object in all interfaces according to selected background color +global DATA + +if isa(DATA,'maingui') + setcolorall(handle); +% setcolormaingui(handle); +end + +%------------------------ +function setcolorall(handle) +global DATA + +switch handle.Type + case 'figure' + set(handle,'Color',DATA.GUISettings.BackgroundColor); + + case 'axes' + if ~(strcmp(handle.Tag,'printuipanel')) + set(handle,'XColorMode','manual','GridColorMode','manual',... + 'GridColor',DATA.GUISettings.BackgroundColor,... + 'XColor',DATA.GUISettings.ForegroundColor,... + 'YColor',DATA.GUISettings.ForegroundColor,... + 'ZColor',DATA.GUISettings.ForegroundColor); + end + + case {'uicontrol','uipanel','uibuttongroup'} + %this handle is specific to Segment 3DP, should have ligth gray background + if (strcmp(handle.Tag,'printuipanel')) + h = findall(handle.printuipanel); + for loop = 1:length(h) + if any(contains({'figure','panel','listbox','edit','text','button'},handle.Tag)) + set(h(loop),'BackgroundColor',[0.94,0.94,0.94]); + set(h(loop),'ForegroundColor',[0, 0, 0]); + end + end + + %this handle is specific to Segment 3DP, should have ligth gray background + elseif (strcmp(handle.Tag,'ribbonuipanel')) + set(handle,'BackgroundColor',[0.94,0.94,0.94]); + set(handle,'ForegroundColor',[0, 0, 0]); + + %other panels can have user defined background color + else + set(handle,'BackgroundColor',DATA.GUISettings.BackgroundColor,... + 'ForegroundColor',DATA.GUISettings.ForegroundColor); + end +end + +%go through all objects +if any(contains({'figure','uipanel','uibuttongroup'},handle.Type)) + kids = handle.Children; + + for i = 1:numel(kids) + try + setcolorall(kids(i)); + catch me %#ok + end + end +end + +%------------------------ + +%------------------------ +function setcolor(handle) +%------------------------ +global DATA + +%find all objects in all interfaces +hstruct = get(handle); +fnames = fieldnames(hstruct); + +if strcmp(hstruct.Type,'uimenu') || strcmp(hstruct.Type,'uicontextmenu') + %Do nothing +else + try + if not(strcmp(hstruct.Type,'axes')) + %set background color + if not(isempty(intersect('Color',fnames))) + disp([handle.Type,': ','Color']) + set(handle,'Color',DATA.GUISettings.BackgroundColor); + end + if not(isempty(intersect('BackgroundColor',fnames))) + disp([handle.Type,': ','BackgroundColor']) + set(handle,'BackgroundColor',DATA.GUISettings.BackgroundColor); + end + end + + %set text color + if not(isempty(intersect('ForegroundColor',fnames))) + disp([handle.Type,': ','ForegroundColor']) + set(handle,'ForegroundColor',DATA.GUISettings.ForegroundColor); + end + if strcmp(hstruct.Type,'axes') + disp([handle.Type,': ','XColorMode']) + disp([handle.Type,': ','GridColorMode']) + disp([handle.Type,': ','GridColor']) + set(handle,'XColorMode','manual'); + set(handle,'GridColorMode','manual'); + set(handle,'GridColor',DATA.GUISettings.BackgroundColor); + end + if not(isempty(intersect('XColor',fnames))) + disp([handle.Type,': ','XColor']) + set(handle,'XColor',DATA.GUISettings.ForegroundColor); + end + if not(isempty(intersect('YColor',fnames))) + disp([handle.Type,': ','YColor']) + set(handle,'YColor',DATA.GUISettings.ForegroundColor); + end + if not(isempty(intersect('ZColor',fnames))) + disp([handle.Type,': ','ZColor']) + set(handle,'ZColor',DATA.GUISettings.ForegroundColor); + end + + catch + disp('Error in set color'); + end +end + +%go through all objects +kids = hstruct.Children; + +for i = 1:numel(kids) + try + if not(strcmp(kids(i).Parent.Type,'axes')) + if not(strcmp(kids(i).Tag,'printuipanel')) + setcolor(kids(i)); + end + end + catch me %#ok + end +end + +%change background color and text color for specific objects +% lgcolor = [0.94 0.94 0.94]; +% try +% set(DATA.Handles.iconuipanel,'BackgroundColor',lgcolor); +% catch +% end +% try +% set(DATA.Handles.permanentaxes,'Color',lgcolor); +% catch +% end +% try +% set(DATA.Handles.ribbonaxes,'Color',lgcolor); +% catch +% end +% try +% set(DATA.Handles.configaxes,'Color',lgcolor); +% catch +% end diff --git a/source/setupicon.m b/source/setupicon.m new file mode 100644 index 0000000..03516d1 --- /dev/null +++ b/source/setupicon.m @@ -0,0 +1,61 @@ +function setupicon(fig) +%Set up software icon for mygui figures. +%Use Segment's icons instead of Mathworks icon. +% +%Note: this function uses the undocumented JavaFrame property which +%may become obsoleted in a future Matlab release (still supported in +%Matlab 2021a). This produces a warning message in the Command Window, +%which is disabled. + +global DATA + +%--- Get icon according to software in use +%No icon if no software is running, e.g. software testing or translating +if isempty(DATA) %|| ~isfield(DATA,'ProgramName') + return; +end +try + prgmname = DATA.ProgramName; +catch + return +end + +if strcmp(prgmname, 'Segment') + if isdeployed + file = 'icon_segment.png'; + else + file = fullfile([DATA.SegmentFolder filesep 'segment_resources'],'icon_segment.png'); + end + +elseif strcmp(prgmname, 'Segment CMR') + if isdeployed + file = 'icon_cmr.png'; + else + file = fullfile([DATA.SegmentFolder filesep 'segmentcmr_resources'],'icon_cmr.png'); + end + +elseif strcmp(prgmname, 'Segment CT') + if isdeployed + file = 'icon_ct.png'; + else + file = fullfile([DATA.SegmentFolder filesep 'segmentct_resources'],'icon_ct.png'); + end + +elseif strcmp(prgmname, 'Segment 3DPrint') + if isdeployed + file = 'icon_3dp.png'; + else + file = fullfile([DATA.SegmentFolder filesep 'segment3dp_resources'],'icon_3dp.png'); + end +end + +%--- Set up icon +%Disable warning message about JavaFrame +warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); +%Access the underlying Java object +h = get(handle(fig),'JavaFrame'); +%Set new icon +icon = javax.swing.ImageIcon(file); +h.setFigureIcon(icon); +%Enable warning message about JavaFrame +warning('on','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); \ No newline at end of file diff --git a/source/setuplicense.p b/source/setuplicense.p index 652bb8a..4e9598a 100644 Binary files a/source/setuplicense.p and b/source/setuplicense.p differ diff --git a/source/setupwarningimage.mat b/source/setupwarningimage.mat new file mode 100644 index 0000000..b5f18ca Binary files /dev/null and b/source/setupwarningimage.mat differ diff --git a/source/showdicominfo.m b/source/showdicominfo.m index 9e750ac..84cc08e 100644 --- a/source/showdicominfo.m +++ b/source/showdicominfo.m @@ -8,31 +8,31 @@ function showdicominfo(filename) if nargin==0 filename = DATA.Preview.PreviewFile; -end; +end %Check if not a filename pos = strfind(filename,'_Callback'); if ~isempty(pos) eval(filename); %it is not a filename, it is a function return; -end; +end %Check if copy_Callback if isequal(filename,'copy_Callback') copy_Callback; return; -end; +end %Temporary switch -stable = false; +stable = true; if ~exist(filename,'file') myfailed(dprintf('Could not find file %s.',filename)); return; -end; +end %debugging -system(sprintf('dcmdump%s "%s" > temp.txt',platformextension,filename)); +%system(sprintf('dcmdump%s "%s" > temp.txt',platformextension,filename)); set(gcf,'pointer','watch'); %info = dicominfo(filename) @@ -49,14 +49,14 @@ function showdicominfo(filename) dinfo = fastdicominfo(filename); if ischar(dinfo) error(dinfo) - end; - end; - end; + end + end + end catch me myfailed('Major problems parsing file.'); mydispexception(me); dinfo.Error = 'Could not parse the file using ordninary parser. DICOM?'; -end; +end fields = fieldnames(dinfo); [~,ind] = sort(fields); @@ -68,18 +68,18 @@ function showdicominfo(filename) for loop=1:length(fields) if length(fields{loop})>maxlen maxlen = length(fields{loop}); - end; -end; + end +end priv = false(length(fields),1); for loop=1:length(fields) if findstr(fields{loop},'Private') priv(loop) = true; - end; + end name = [fields{loop} repmat(' ',1,maxlen-length(fields{loop}))]; f = getfield(dinfo,fields{loop}); res{loop} = writefield(f,name); -end; +end res = res([find(not(priv));find(priv)]); set(gcf,'pointer','arrow'); @@ -106,13 +106,13 @@ function showdicominfo(filename) res = sprintf('%s:%s',name,mynum2str(f)); else res = sprintf('%s:[double size %s]',name,num2str(size(f))); - end; + end case 'single' if numel(f)<=10 res = sprintf('%s:%s',name,mynum2str(f)); else res = sprintf('%s:[single size %s]',name,num2str(size(f))); - end; + end case 'char' res = sprintf('%s:%s',name,f); case {'int8','uint8','int16','uint16','int32','uint32','int64','uint64'} @@ -120,7 +120,7 @@ function showdicominfo(filename) res = sprintf('%s:%s',name,sprintf('%d ',f)); else res = sprintf('%s:[%d] ... %s',name,numel(f),sprintf('%d ',f(1:5))); - end; + end case 'struct' if length(fieldnames(f))>2 res = sprintf('%s:[Struct]',name); @@ -132,13 +132,13 @@ function showdicominfo(filename) tempstri = [tempstri sprintf('%s:%s',subnames{subloop},getfield(f,subnames{subloop})) ' ']; %#ok else tempstri = [tempstri sprintf('%s:%s',subnames{subloop},class(getfield(f,subnames{subloop}))) ' ']; %#ok - end; - end; + end + end res = sprintf('%s=>%s',name,tempstri); - end; + end otherwise res = sprintf('%s:[%s]',name,class(f)); -end; +end %------------------------- function stri = mynum2str(vec) @@ -158,8 +158,8 @@ function showdicominfo(filename) else disp(sprintf('New: %s',writefield(gui.dinfo.(fnames{loop}),fnames{loop}))); %#ok disp(sprintf('Old: %s',writefield(gui.olddinfo.(fnames{loop}),fnames{loop}))); %#ok - end; -end; + end +end %---------------------- function store_Callback %#ok @@ -187,7 +187,7 @@ function showdicominfo(filename) pos = find(stri==':',1); if ~isempty(pos) stri = stri(pos+1:end); -end; +end segment('cell2clipboard',{stri}); diff --git a/source/shuntvalve.m b/source/shuntvalve.m index 3fbeeba..a2ca40c 100644 --- a/source/shuntvalve.m +++ b/source/shuntvalve.m @@ -32,9 +32,10 @@ fwpulmo = []; bwpulmo = []; eddycheck = false; +isinvisible = true; for floop = flowmagnitudeno if SET(floop).RoiN > 0 - reportflow('init',floop,eddycheck); + reportflow('init',floop,eddycheck,isinvisible); rois = reportflow('getroiname'); aaf = find(strcmp('Aortic ascending flow',rois), 1); paf = find(strcmp('Pulmonary artery',rois), 1); @@ -58,7 +59,7 @@ end %--------------------- -function result = qpqs +function result = qpqs %#ok %--------------------- %Calculate Qp/Qs and display result in a message box @@ -70,12 +71,11 @@ if nargout == 0 if ~isempty(result) - stri = sprintf([... - 'SV aorta: %0.1f ml\n'... + stri = dprintf(['SV aorta: %0.1f ml\n'... 'SV pulmonalis: %0.1f ml\n'... 'Qp/Qs ratio: %0.0f %%'],... svaorta,svpulmo,100*result); - msgbox(stri, 'Qp/Qs'); + mymsgbox(stri, 'Qp/Qs'); else myfailed('Could not find flows for both aorta and pulmonalis'); end @@ -86,6 +86,10 @@ %---------------------------------------------------- %Calculate regurgitant fractions for mitralis and tricusp global SET +mitrvol = []; +mitrfrac = []; +tricvol = []; +tricfrac = []; cineshortaxisno = findfunctions('findcineshortaxisno'); if isempty(cineshortaxisno) || SET(cineshortaxisno).SV == 0 myfailed('SV from cine short-axis image stack is missing.'); @@ -95,15 +99,13 @@ stri = ''; if ~isempty(bwaorta) - stri = [stri sprintf([... - 'Regurgitant volume aorta: %0.0f ml\n'... + stri = [stri dprintf(['Regurgitant volume aorta: %0.0f ml\n'... 'Regurgitant fraction aorta: %0.0f %%\n'],... bwaorta,100*bwaorta/fwaorta)]; end if ~isempty(bwpulmo) - stri = [stri sprintf([... - 'Regurgitant volume pulmonary artery: %0.0f ml\n'... + stri = [stri dprintf(['Regurgitant volume pulmonary artery: %0.0f ml\n'... 'Regurgitant fraction pulmonary artery: %0.0f %%\n'],... bwpulmo,100*bwpulmo/fwpulmo)]; end @@ -112,32 +114,86 @@ if lvsv > 0 && ~isempty(fwaorta) mitrvol = lvsv - fwaorta; mitrfrac = mitrvol / lvsv; - stri = [stri sprintf([... - 'Regurgitant volume mitralis: %0.0f ml\n'... + stri = [stri dprintf(['Regurgitant volume mitralis: %0.0f ml\n'... 'Regurgitant fraction mitralis: %0.0f %%\n'],... mitrvol,100*mitrfrac)]; -else - mitrvol = []; - mitrfrac = []; end rvsv = SET(cineshortaxisno).RVSV; if rvsv > 0 && ~isempty(fwpulmo) tricvol = rvsv - fwpulmo; tricfrac = tricvol / rvsv; - stri = [stri sprintf([... - 'Regurgitant volume tricusp: %0.0f ml\n'... + stri = [stri dprintf(['Regurgitant volume tricusp: %0.0f ml\n'... 'Regurgitant fraction tricusp: %0.0f %%'],... tricvol,100*tricfrac)]; -else - tricvol = []; - tricfrac = []; end if nargout == 0 if ~isempty(stri) - msgbox(stri, 'Shunt and Valve analysis'); + mymsgbox(stri, 'Shunt and Valve analysis'); else myfailed('Could not find sufficient stroke volumes') end -end \ No newline at end of file +end + +%----------------------------------------------------------------- +function [lpafrac,rpafrac,svrpa,svlpa] = getlungflow %#ok called from report2clipboard +%----------------------------------------------------------------- +%Calculate and return stroke volume and right/left pulmonary blood flow +%fractions +global SET +%Find magnitude image on flow +[~,~,flowno] = findfunctions('findno'); +flowmagnitudeno = []; +for loop = flowno + if loop == SET(loop).Flow.MagnitudeNo + flowmagnitudeno = [flowmagnitudeno loop]; %#ok + end +end + +%Find proper vessels for analysis +svrpa = []; +svlpa = []; +svpa = []; +eddycheck = false; +isinvisible = true; +for floop = flowmagnitudeno + if SET(floop).RoiN > 0 + reportflow('init',floop,eddycheck,isinvisible); + rois = reportflow('getroiname'); + rpaind = find(strcmp('RPA',rois), 1); + lpaind = find(strcmp('LPA',rois), 1); + paind = find(strcmp('Pulmonary Artery',rois), 1); + if ~isempty(rpaind) || ~isempty(lpaind) + nettoflow = reportflow('gettotal'); % netto flow of all ROIs + if ~isempty(rpaind) + svrpa = nettoflow(rpaind); + end + if ~isempty(lpaind) + svlpa = nettoflow(lpaind); + end + if ~isempty(paind) + svpa = nettoflow(paind); + end + end + reportflow('close_Callback'); + end +end +lpafrac = []; +rpafrac = []; +% calculate fraction for RPA and LPA depending whether both +% exist or not +if ~isempty(svrpa) && ~isempty(svlpa) + svlung = svlpa + svrpa; + lpafrac = svlpa/svlung; + rpafrac = svrpa/svlung; +else + if ~isempty(svlpa) && ~isempty(svpa) + lpafrac = svlpa/svpa; + end + if ~isempty(svrpa) && ~isempty(svpa) + rpafrac = svrpa/svpa; + end +end + + diff --git a/source/sigge_resampler.mexw32 b/source/sigge_resampler.mexw32 deleted file mode 100644 index d2aefa4..0000000 Binary files a/source/sigge_resampler.mexw32 and /dev/null differ diff --git a/source/slicereport.fig b/source/slicereport.fig index bb6913b..b7bf048 100644 Binary files a/source/slicereport.fig and b/source/slicereport.fig differ diff --git a/source/slicereport.m b/source/slicereport.m index db1231f..a3298d2 100644 --- a/source/slicereport.m +++ b/source/slicereport.m @@ -13,22 +13,20 @@ function slicereport(type) %Initiate GUI global DATA SET NO -set(DATA.Handles.reportpersliceicon,'state','off'); - if SET(NO).TSize<2 myfailed('Data needs to be time resolved.',DATA.GUI.Segment); return; -end; +end if isempty(SET(NO).EndoX) myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end if sum(findfunctions('findslicewithendo',NO))==0 myfailed('No LV endocardium available.',DATA.GUI.Segment); return; -end; +end tempnos=NO; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -40,7 +38,6 @@ function slicereport(type) gui = mygui('slicereport.fig'); DATA.GUI.SliceReport = gui; - temp = get(gui.handles.sectorslistbox,'String'); gui.numsectors = str2num(temp{mygetlistbox(gui.handles.sectorslistbox)}); %#ok gui.slice = SET(NO).CurrentSlice; @@ -63,6 +60,7 @@ function slicereport(type) end update; %Update more +try set(gui.figure1,'Visible','on'); catch, end %---------------------- function close_Callback @@ -89,7 +87,7 @@ function slicereport(type) drawnow; DATA.MovieFrame = mygetframe(gui.fig); export('exportmovierecorder_Callback','newframe'); -end; +end parameter; %-------------- @@ -112,12 +110,12 @@ function slicereport(type) if isequal(SET(NO).Point.Label{loop},'Sector start') if ~isnan(px) mywarning('More than one sector start found, take ''latest''.',DATA.GUI.Segment); - end; + end px = SET(NO).Point.X(loop); py = SET(NO).Point.Y(loop); pz = SET(NO).Point.Z(loop); - end; - end; + end + end if isnan(px) myfailed('Could not find an annotation point labelled ''Sector start''',DATA.GUI.Segment); set(gui.handles.rotationfromannotationcheckbox,'value',0); @@ -126,15 +124,15 @@ function slicereport(type) mx = mean(SET(NO).EndoX(:,SET(NO).EDT,pz)); my = mean(SET(NO).EndoY(:,SET(NO).EDT,pz)); SET(NO).SectorRotation = angle(complex(my-py,mx-px))*180/pi; - end; + end set(gui.handles.rotationslider,'value',... SET(NO).SectorRotation); -end; +end if gui.numsectors>DATA.Pref.RadialProfiles mywarning('Reporting in more sectors than evaluating. Reverting back to same number of sectors as evaluation the profile along. For details see preferences. ',DATA.GUI.Segment); gui.numsectors = DATA.Pref.RadialProfiles; -end; +end [gui.meanx,gui.meany,gui.sectors] = ... calcfunctions('findmeaninsectorslice',gui.type,DATA.NumPoints,SET(NO).CurrentTimeFrame,gui.slice,gui.numsectors); @@ -146,19 +144,13 @@ function slicereport(type) colormap(gray(256)); axis image off; hold on; -gui.handles.endocontour = plot(... - SET(NO).EndoY(:,tf,gui.slice),... - SET(NO).EndoX(:,tf,gui.slice),... - 'r-'); +gui.handles.endocontour = line('parent',gui.handles.playaxes,'XData',SET(NO).EndoY(:,tf,gui.slice),'YData',SET(NO).EndoX(:,tf,gui.slice),'Color','r','LineStyle','-'); if ~isempty(SET(NO).EpiX) - gui.handles.epicontour = plot(... - SET(NO).EpiY(:,tf,gui.slice),... - SET(NO).EpiX(:,tf,gui.slice),... - 'g-'); + gui.handles.epicontour = line('parent',gui.handles.playaxes,'XData',SET(NO).EpiY(:,tf,gui.slice),'YData',SET(NO).EpiX(:,tf,gui.slice),'Color','g','LineStyle','-'); else - gui.handles.epicontour = plot(NaN,NaN); -end; + gui.handles.epicontour = line('parent',gui.handles.playaxes,'XData',NaN,'YData',NaN); +end hold off; %--- Plot overview image @@ -167,19 +159,13 @@ function slicereport(type) axis image off; hold on; -h = plot(... - SET(NO).EndoY(:,tf,gui.slice),... - SET(NO).EndoX(:,tf,gui.slice),... - 'r-'); +h = line('parent',gui.handles.imageaxes,'XData',SET(NO).EndoY(:,tf,gui.slice),'YData',SET(NO).EndoX(:,tf,gui.slice),'Color','r','LineStyle','-'); set(h,'linewidth',3); if ~isempty(SET(NO).EpiX) - h = plot(... - SET(NO).EpiY(:,tf,gui.slice),... - SET(NO).EpiX(:,tf,gui.slice),... - 'g-'); + h = line('parent',gui.handles.imageaxes,'XData',SET(NO).EpiY(:,tf,gui.slice),'YData',SET(NO).EpiX(:,tf,gui.slice),'Color','g','LineStyle','-'); else - h = plot(NaN,NaN); -end; + h = line('parent',gui.handles.imageaxes,'XData',NaN,'YData',NaN); +end set(h,'linewidth',3); if not(isnan(gui.meanx)) @@ -202,19 +188,17 @@ function slicereport(type) SET(NO).EndoX(gui.sectors(loop+1),tf,gui.slice)); xpos = SET(NO).EndoY(gui.sectors(loop),tf,gui.slice); ypos = SET(NO).EndoX(gui.sectors(loop),tf,gui.slice); - end; - plot([gui.meany xpos],[gui.meanx ypos],'y-'); + end + line('parent',gui.handles.imageaxes,'XData',[gui.meany xpos],'YData',[gui.meanx ypos],'Color','y','LineStyle','-'); if (loop==1) - plot(... - [xpos xpos-(gui.meany-xpos)],... - [ypos ypos-(gui.meanx-ypos)],'y-'); - end; + line('parent',gui.handles.imageaxes,'XData',[xpos xpos-(gui.meany-xpos)],'YData',[ypos ypos-(gui.meanx-ypos)],'Color','y','LineStyle','-'); + end if (loop==1)||(gui.numsectors<20) h = text(xposm,yposm,sprintf('%d',loop)); set(h,'color','y','fontsize',14); - end; - end; %loop -end; %if isnan + end + end %loop +end %if isnan hold off; %------------- @@ -253,14 +237,14 @@ function slicereport(type) gui.type = 'epi'; wallthickness = calcfunctions('calcwallthickness',gui.numsectors,NO); gui.outdata = squeeze(wallthickness(:,gui.slice,:)); - gui.title = 'Wallthickness'; + gui.title = dprintf('Wall thickness'); gui.outunit = 'mm'; - end; + end case 2 %Fractional thickening if isequal(SET(NO).EDT,SET(NO).EST) mywarning('Warning, end-diastole occurs at the same time as end-systole. Use autodetect under edit menu.',DATA.GUI.Segment); - end; + end if isempty(SET(NO).EpiX) myfailed('No LV epicardium available.',DATA.GUI.Segment); set(gui.handles.parameterlistbox,'value',3); @@ -272,9 +256,9 @@ function slicereport(type) minthick = repmat(gui.outdata(:,SET(NO).EDT),[1 SET(NO).TSize]); gui.outdata = (gui.outdata-minthick)./minthick; gui.outdata = gui.outdata*100; - gui.title = 'Fractional wallthickening'; + gui.title = dprintf('Fractional wallthickening'); gui.outunit = '%'; - end; + end case 3 %Radial velocity gui.type = 'endo'; @@ -284,8 +268,8 @@ function slicereport(type) 'endo',radvel,gui.slice,gui.numsectors); else gui.outdata = []; - end; - gui.title = 'Radial velocity'; + end + gui.title = dprintf('Radial velocity'); gui.outunit = 'cm/s'; case 4 %Radius @@ -296,38 +280,40 @@ function slicereport(type) 'endo',rad,gui.slice,gui.numsectors); else gui.outdata = []; - end; - gui.title = 'Radius'; + end + gui.title = dprintf('Radius'); gui.outunit = 'mm'; otherwise myfailed('Unknown option to reportslice.',DATA.GUI.Segment); -end; +end gui.outdata = squeeze(gui.outdata); axes(gui.handles.plotaxes); -if not(isempty(gui.outdata)) - h = plot(t,gui.outdata); +if not(isempty(gui.outdata)) + h = plot(repmat(t,size(gui.outdata,1),1)',gui.outdata'); set(h,'linewidth',2,'marker','.'); %hold on; %plot([t(1),t(end)],[0 0],'k:'); %hold off; - title(sprintf('%s [%s]',gui.title,gui.outunit)); + title(sprintf('%s [%s]',gui.title,gui.outunit),'color',DATA.GUISettings.ForegroundColor); %Fix legend if gui.numsectors<20 l = cell(1,gui.numsectors); - for loop=1:gui.numsectors; + for loop=1:gui.numsectors l{loop} = dprintf('Sector %d',loop); - end; + end legend(l{:}); - end; + end - ylabel(sprintf('[%s]',gui.outunit)); + ylabel(sprintf('[%s]',gui.outunit),'color',DATA.GUISettings.ForegroundColor); + set(gui.handles.plotaxes,'xcolor',DATA.GUISettings.ForegroundColor); + set(gui.handles.plotaxes,'ycolor',DATA.GUISettings.ForegroundColor); else - plot(t,zeros(size(t))); - title(dprintf('%s not available.',gui.title)); -end; -xlabel('Time'); + plot('parent',gui.handles.plotaxes,'XData',t,'YData',zeros(size(t))); + title(dprintf('%s not available.',gui.title),'color',DATA.GUISettings.ForegroundColor); +end +xlabel(dprintf('Time')); sector; %------------------- @@ -345,12 +331,12 @@ function slicereport(type) set(gui.handles.epicontour,... 'xdata',SET(NO).EpiY(:,SET(NO).CurrentTimeFrame,gui.slice),... 'ydata',SET(NO).EpiX(:,SET(NO).CurrentTimeFrame,gui.slice)); -end; +end if DATA.Record drawnow; DATA.MovieFrame = mygetframe(gui.fig); export('exportmovierecorder_Callback','newframe'); -end; +end %------------ function play @@ -368,10 +354,10 @@ function slicereport(type) pause(0.5*SET(NO).BeatTime/SET(NO).TSize); %pause(0.01); frameupdate; - end; + end catch %#ok %Do nothing -end; +end %----------------------- function export_Callback @@ -386,15 +372,15 @@ function slicereport(type) stri = [stri sprintf('Time\t')]; for sector=1:gui.numsectors stri = [stri sprintf('Sector%d\t',sector)]; %#ok -end; +end stri = [stri sprintf('\n')]; for tloop=1:SET(NO).TSize stri = [stri sprintf('%0.5g\t',t(tloop))]; %#ok for sector=1:gui.numsectors stri = [stri sprintf('%0.5g\t',gui.outdata(sector,tloop))]; %#ok - end; + end stri = [stri sprintf('\n')]; %#ok -end; +end clipboard('copy',stri); mymsgbox('Data Exported.','Done!',DATA.GUI.Segment); @@ -406,7 +392,7 @@ function slicereport(type) SET(NO).CurrentTimeFrame=SET(NO).CurrentTimeFrame+1; if SET(NO).CurrentTimeFrame>SET(NO).TSize SET(NO).CurrentTimeFrame=1; -end; +end frameupdate; %------------ @@ -417,7 +403,7 @@ function slicereport(type) SET(NO).CurrentTimeFrame=SET(NO).CurrentTimeFrame-1; if SET(NO).CurrentTimeFrame<1 SET(NO).CurrentTimeFrame=SET(NO).TSize; -end; +end frameupdate; %------------ diff --git a/source/slicesorter.m b/source/slicesorter.m index 9961e96..2099488 100644 --- a/source/slicesorter.m +++ b/source/slicesorter.m @@ -10,8 +10,8 @@ try pathname = DATA.Pref.datapath; catch %#ok - pathname = pwd; -end; + pathname = DATA.SegmentFolder; +end %If loader is running try @@ -22,22 +22,22 @@ if (length(f) == 1) && f(1).isdir pathname = [DATA.Preview.PathName filesep f(1).name]; end - end; + end catch %#ok -end; +end [pathname,ok] = myuigetdir(pathname,'Select folder to sort'); if ~ok - myfailed('Aborted'); +% myfailed('Aborted'); return; -end; +end outpathname = [pathname '-sorted']; ok = mymkdir(outpathname); if ~ok myfailed(dprintf('Could not create output path %s',outpathname)); return; -end; +end f = dir(pathname); @@ -46,7 +46,7 @@ if ~f(loop).isdir %Not a folder => filename filename = [pathname filesep f(loop).name]; - if guessifdicom(filename,1); %1=heuristic mode + if guessifdicom(filename,1) %1=heuristic mode info = fastdicominfo(filename); if ischar(info) || isequal(info.TransferSyntaxUID,'jpeg') || isequal(info.TransferSyntaxUID,'1.2.840.10008.1.2.4.90') @@ -54,8 +54,8 @@ info = fastdicominfo(filename); if ischar(info) error(info); - end; - end; + end + end %Use this instead of sliceLocation which sometimes is buggy normal = cross(info.ImageOrientation(1:3),info.ImageOrientation(4:6)); sl = sum(normal.*info.ImagePosition); @@ -66,12 +66,12 @@ slicestring = [strtrim(info.SeriesDescription) '_']; else slicestring = ''; - end; + end if sl<0 slicestring = [slicestring '-']; %#ok else slicestring = [slicestring '']; %#ok - end; + end slicestring = [slicestring sprintf('%03d',floor(abs(sl)))]; %#ok slicestring = [slicestring '.']; %#ok slicestring = [slicestring sprintf('%03d',round(1000*rem(abs(sl),1)))]; %#ok @@ -79,13 +79,13 @@ newfolder = [outpathname filesep slicestring]; if ~exist(newfolder,'dir') mkdir(newfolder); - end; + end [status,msg] = copyfile(filename,[newfolder filesep f(loop).name]); if ~isequal(status,1) - disp(dprintf('Failed moving file %s. Error message %s',f(loop).name,msg)); %#ok - end; - end; - end; + disp(sprintf('Failed moving file %s. Error message %s',f(loop).name,msg)); + end + end + end h = mywaitbarupdate(h); -end; +end mywaitbarclose(h); diff --git a/source/smoothimage.mexw32 b/source/smoothimage.mexw32 deleted file mode 100644 index 65e07e6..0000000 Binary files a/source/smoothimage.mexw32 and /dev/null differ diff --git a/source/spect.p b/source/spect.p index 36c151b..c9e9d30 100644 Binary files a/source/spect.p and b/source/spect.p differ diff --git a/source/storescp.exe b/source/storescp.exe index 409e02d..705e25c 100644 Binary files a/source/storescp.exe and b/source/storescp.exe differ diff --git a/source/storescu.exe b/source/storescu.exe index 85fd1b0..99b253c 100644 Binary files a/source/storescu.exe and b/source/storescu.exe differ diff --git a/source/straintools.p b/source/straintools.p deleted file mode 100644 index cc216bc..0000000 Binary files a/source/straintools.p and /dev/null differ diff --git a/source/support.site b/source/support.site index 011ddee..22f6e75 100644 Binary files a/source/support.site and b/source/support.site differ diff --git a/source/surfacepoints2D.mexw32 b/source/surfacepoints2D.mexw32 deleted file mode 100644 index 6b2cf94..0000000 Binary files a/source/surfacepoints2D.mexw32 and /dev/null differ diff --git a/source/surfacepoints3D.mexw32 b/source/surfacepoints3D.mexw32 deleted file mode 100644 index 60506a2..0000000 Binary files a/source/surfacepoints3D.mexw32 and /dev/null differ diff --git a/source/surfacepoints4D.mexw32 b/source/surfacepoints4D.mexw32 deleted file mode 100644 index cb17ca7..0000000 Binary files a/source/surfacepoints4D.mexw32 and /dev/null differ diff --git a/source/svd_scaledVar_MC.mat b/source/svd_scaledVar_MC.mat deleted file mode 100644 index c576e55..0000000 Binary files a/source/svd_scaledVar_MC.mat and /dev/null differ diff --git a/source/svd_scaledVar_radial.mat b/source/svd_scaledVar_radial.mat deleted file mode 100644 index 8fbaf43..0000000 Binary files a/source/svd_scaledVar_radial.mat and /dev/null differ diff --git a/source/switchdelineations.fig b/source/switchdelineations.fig index 27c2449..d160064 100644 Binary files a/source/switchdelineations.fig and b/source/switchdelineations.fig differ diff --git a/source/t1map.fig b/source/t1map.fig index bac56b1..b773125 100644 Binary files a/source/t1map.fig and b/source/t1map.fig differ diff --git a/source/t2map.fig b/source/t2map.fig index 946f967..940b736 100644 Binary files a/source/t2map.fig and b/source/t2map.fig differ diff --git a/source/t2wmarsegmentation.p b/source/t2wmarsegmentation.p index 58a4f48..b538237 100644 Binary files a/source/t2wmarsegmentation.p and b/source/t2wmarsegmentation.p differ diff --git a/source/thumbnails.p b/source/thumbnails.p index 3a51072..b33db7a 100644 Binary files a/source/thumbnails.p and b/source/thumbnails.p differ diff --git a/source/tools.m b/source/tools.m index 7f6b5e4..2bb2de6 100644 --- a/source/tools.m +++ b/source/tools.m @@ -38,20 +38,20 @@ function setcurrenttimeframeasfirst_Callback(applyto,showmessage) %#ok if SET(NO).TSize<2 myfailed('Data needs to be time resolved.',DATA.GUI.Segment); return; -end; +end if showmessage - if not(yesno('Setting current timeframe as first timeframe is not undoable. Are you sure?',[],DATA.GUI.Segment)); + if not(yesno('Setting current timeframe as first timeframe is not undoable. Are you sure?',[],DATA.GUI.Segment)) return; - end; + end end if ~isempty(SET(NO).LevelSet) if not(yesno('General segmentation data exists, this is not yet supported, data will be cleared. Are you sure?',[],DATA.GUI.Segment)) return; - end; + end SET(NO).LevelSet = []; -end; +end shiftvec1 = zeros(1,2); shiftvec2 = zeros(1,2); @@ -62,7 +62,7 @@ function setcurrenttimeframeasfirst_Callback(applyto,showmessage) %#ok %checks if flow data nos=SET(NO).Linked; -for no=nos; +for no=nos for zloop=slices %Image SET(no).IM(:,:,:,zloop) = circshift(SET(no).IM(:,:,:,zloop),shiftvec3); @@ -71,55 +71,55 @@ function setcurrenttimeframeasfirst_Callback(applyto,showmessage) %#ok if ~isempty(SET(no).EndoX) SET(no).EndoX(:,:,zloop) = circshift(SET(no).EndoX(:,:,zloop),shiftvec2); SET(no).EndoY(:,:,zloop) = circshift(SET(no).EndoY(:,:,zloop),shiftvec2); - end; + end if ~isempty(SET(no).EpiX) SET(no).EpiX(:,:,zloop) = circshift(SET(no).EpiX(:,:,zloop),shiftvec2); SET(no).EpiY(:,:,zloop) = circshift(SET(no).EpiY(:,:,zloop),shiftvec2); - end; + end if ~isempty(SET(no).RVEndoX) SET(no).RVEndoX(:,:,zloop) = circshift(SET(no).RVEndoX(:,:,zloop),shiftvec2); SET(no).RVEndoY(:,:,zloop) = circshift(SET(no).RVEndoY(:,:,zloop),shiftvec2); - end; + end if ~isempty(SET(no).RVEpiX) SET(no).RVEpiX(:,:,zloop) = circshift(SET(no).RVEpiX(:,:,zloop),shiftvec2); SET(no).RVEpiY(:,:,zloop) = circshift(SET(no).RVEpiY(:,:,zloop),shiftvec2); - end; + end %Pins if ~isempty(SET(no).EndoPinX) SET(no).EndoPinX(:,zloop) = circshift(SET(no).EndoPinX(:,zloop),shiftvec1); SET(no).EndoPinY(:,zloop) = circshift(SET(no).EndoPinY(:,zloop),shiftvec1); - end; + end if ~isempty(SET(no).EpiPinX) SET(no).EpiPinX(:,zloop) = circshift(SET(no).EpiPinX(:,zloop),shiftvec1); SET(no).EpiPinY(:,zloop) = circshift(SET(no).EpiPinY(:,zloop),shiftvec1); - end; + end if ~isempty(SET(no).RVEndoPinX) SET(no).RVEndoPinX(:,zloop) = circshift(SET(no).RVEndoPinX(:,zloop),shiftvec1); SET(no).RVEndoPinY(:,zloop) = circshift(SET(no).RVEndoPinY(:,zloop),shiftvec1); - end; + end if ~isempty(SET(no).EpiPinX) SET(no).RVEpiPinX(:,zloop) = circshift(SET(no).RVEpiPinX(:,zloop),shiftvec1); SET(no).RVEpiPinY(:,zloop) = circshift(SET(no).RVEpiPinY(:,zloop),shiftvec1); - end; + end %Interp Points if ~isempty(SET(no).EndoInterpX) SET(no).EndoInterpX(:,zloop) = circshift(SET(no).EndoInterpX(:,zloop),shiftvec1); SET(no).EndoInterpY(:,zloop) = circshift(SET(no).EndoInterpY(:,zloop),shiftvec1); - end; + end if ~isempty(SET(no).EpiInterpX) SET(no).EpiInterpX(:,zloop) = circshift(SET(no).EpiInterpX(:,zloop),shiftvec1); SET(no).EpiInterpY(:,zloop) = circshift(SET(no).EpiInterpY(:,zloop),shiftvec1); - end; + end if ~isempty(SET(no).RVEndoInterpX) SET(no).RVEndoInterpX(:,zloop) = circshift(SET(no).RVEndoInterpX(:,zloop),shiftvec1); SET(no).RVEndoInterpY(:,zloop) = circshift(SET(no).RVEndoInterpY(:,zloop),shiftvec1); - end; + end if ~isempty(SET(no).RVEpiInterpX) SET(no).RVEpiInterpX(:,zloop) = circshift(SET(no).RVEpiInterpX(:,zloop),shiftvec1); SET(no).RVEpiInterpY(:,zloop) = circshift(SET(no).RVEpiInterpY(:,zloop),shiftvec1); - end; + end %Viability (ignored) @@ -129,8 +129,8 @@ function setcurrenttimeframeasfirst_Callback(applyto,showmessage) %#ok SET(no).Roi(rloop).X = circshift(SET(no).Roi(rloop).X,shiftvec2); SET(no).Roi(rloop).Y = circshift(SET(no).Roi(rloop).Y,shiftvec2); SET(no).Roi(rloop).T = circshift(SET(no).Roi(rloop).T,shiftvec1); - end; - end; + end + end %Levelset %Ignore, see error check above. @@ -144,7 +144,7 @@ function setcurrenttimeframeasfirst_Callback(applyto,showmessage) %#ok SET(no).StrainTagging = []; end - end; + end if isequal(applyto,'all') if SET(NO).EDT ~= 1 || SET(NO).EST ~= 1 %shift ED and ES definitions @@ -154,11 +154,23 @@ function setcurrenttimeframeasfirst_Callback(applyto,showmessage) %#ok SET(NO).CurrentTimeFrame = mod(SET(NO).CurrentTimeFrame+shiftvec1(1),SET(NO).TSize); end end -segment('updatemodeldisplay'); -segment('makeviewim',DATA.CurrentPanel,NO); -drawfunctions('drawimageno',NO); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); calcfunctions('calcvolume',NO); DATA.updatevolumeaxes; +DATA.updatetimebaraxes; + +%------------------------- +function cleardatalevelset +%------------------------- +%Clears DATA.LevelSet (OBS not SET.LevelSet) + +global DATA + +DATA.LevelSet.SpeedIM = []; +DATA.LevelSet.EDGE0 = []; +DATA.LevelSet.EDGE1 = []; +DATA.LevelSet.GradientPart = []; %------------------------------------------------------ function removeduplicatetimeframes_Callback(duplicates) %#ok @@ -176,8 +188,8 @@ function removeduplicatetimeframes_Callback(duplicates) %#ok if not(ok) myfailed('Invalid number of duplicates or aborted.'); return; - end; -end; + end +end %Remove it ind = false(1,SET(NO).TSize); @@ -191,16 +203,16 @@ function addnoise_Callback(f) %#ok global DATA SET NO if nargin==0 - if not(yesno('Adding noise is not undoable. Are you sure?',[],DATA.GUI.Segment)); + if not(yesno('Adding noise is not undoable. Are you sure?',[],DATA.GUI.Segment)) return; - end; + end [f,ok] = mygetnumber('Enter std of noise','STD',0.01,0,inf); if ~ok myfailed('Invalid STD or aborted.',DATA.GUI.Segment); return; - end; -end; + end +end tempnos=NO; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -210,7 +222,8 @@ function addnoise_Callback(f) %#ok SET(NO).IM = SET(NO).IM+f*randn(size(SET(NO).IM)); -segment('viewrefresh_Callback'); +%segment('viewrefresh_Callback'); +viewfunctions('setview') %----------------------------------------- function temporalmeanvalue_Callback(silent) %#ok @@ -228,8 +241,8 @@ function temporalmeanvalue_Callback(silent) %#ok if not(silent) myfailed('Already non time resolved. Aborted.',DATA.GUI.Segment); return; - end; -end; + end +end meanovertime = zeros(SET(NO).XSize,SET(NO).YSize,1,SET(NO).ZSize); %mean temporal image if silent == 0 @@ -257,7 +270,7 @@ function temporalmeanvalue_Callback(silent) %#ok [~, timeframe] = min(error); %find the time frame with the smallest difference to the mean temporal image if silent == 0 %plot the difference between the mean temporal image and all time frames - figure,plot(timeframe,error(timeframe),'ro',1:SET(NO).TSize,error,'b'), grid on,xlabel('time frame'),ylabel('intensity error compared to mean image') + figure,plot(timeframe,error(timeframe),'ro',1:SET(NO).TSize,error,'b'), grid on,xlabel(dprintf('Time frame')),ylabel(dprintf('Intensity error compared to mean image')) output{1,1} = 'timeframe'; output{1,2} = 'error'; for loop = 1:length(error) @@ -386,7 +399,10 @@ function temporalmeanvalue_Callback(silent) %#ok %erase ROIs for other time frames roi('roidelete_Callback',eraserois); end - roistf=[];for roiloop = 1:SET(NO).RoiN,roistf(roiloop) = SET(NO).Roi(roiloop).T;end + roistf=[]; + for roiloop = 1:SET(NO).RoiN + roistf(roiloop) = SET(NO).Roi(roiloop).T; + end keeprois = find(roistf == timeframe); if ~isempty(keeprois) for roiloop = 1:length(keeprois) @@ -396,10 +412,10 @@ function temporalmeanvalue_Callback(silent) %#ok end %LevelSet if ~isempty(SET(NO).LevelSet) - mydisp('General segmentation tool data is erased in the mean temporal image stack.'); + disp('3D segmentation data is erased in the mean temporal image stack.'); SET(NO).LevelSet = []; %clear DATA.LevelSet - segment('cleardatalevelset'); + cleardatalevelset end %Add stack links @@ -424,7 +440,7 @@ function temporalmeanvalue_Callback(silent) %#ok number = number+1; end if silent == 0 - segment('viewrefreshall_Callback'); + viewfunctions('setview'); end %-------------------------------------- @@ -437,7 +453,7 @@ function extraslice_Callback(type) %#ok if nargin==0 type = 'basal'; -end; +end %--- Extra basal switch type @@ -449,36 +465,36 @@ function extraslice_Callback(type) %#ok if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinX = cat(2,SET(NO).EndoPinX(:,1),SET(NO).EndoPinX); SET(NO).EndoPinY = cat(2,SET(NO).EndoPinY(:,1),SET(NO).EndoPinY); - end; + end if ~isempty(SET(NO).EpiPinX) SET(NO).EpiPinX = cat(2,SET(NO).EpiPinX(:,1),SET(NO).EpiPinX); SET(NO).EpiPinY = cat(2,SET(NO).EpiPinY(:,1),SET(NO).EpiPinY); - end; + end if ~isempty(SET(NO).RVEndoPinX) SET(NO).RVEndoPinX = cat(2,SET(NO).RVEndoPinX(:,1),SET(NO).RVEndoPinX); SET(NO).RVEndoPinY = cat(2,SET(NO).RVEndoPinY(:,1),SET(NO).RVEndoPinY); - end; + end if ~isempty(SET(NO).RVEpiPinX) SET(NO).RVEpiPinY = cat(2,SET(NO).RVEpiPinY(:,1),SET(NO).RVEpiPinY); SET(NO).RVEpiPinX = cat(2,SET(NO).RVEpiPinX(:,1),SET(NO).RVEpiPinX); - end; + end if ~isempty(SET(NO).EndoInterpX) SET(NO).EndoInterpX = cat(2,SET(NO).EndoInterpX(:,1),SET(NO).EndoInterpX); SET(NO).EndoInterpY = cat(2,SET(NO).EndoInterpY(:,1),SET(NO).EndoInterpY); - end; + end if ~isempty(SET(NO).EpiInterpX) SET(NO).EpiInterpX = cat(2,SET(NO).EpiInterpX(:,1),SET(NO).EpiInterpX); SET(NO).EpiInterpY = cat(2,SET(NO).EpiInterpY(:,1),SET(NO).EpiInterpY); - end; + end if ~isempty(SET(NO).RVEndoInterpX) SET(NO).RVEndoInterpX = cat(2,SET(NO).RVEndoInterpX(:,1),SET(NO).RVEndoInterpX); SET(NO).RVEndoInterpY = cat(2,SET(NO).RVEndoInterpY(:,1),SET(NO).RVEndoInterpY); - end; + end if ~isempty(SET(NO).RVEpiInterpX) SET(NO).RVEpiInterpX = cat(2,SET(NO).RVEpiInterpX(:,1),SET(NO).RVEpiInterpX); SET(NO).RVEpiInterpY = cat(2,SET(NO).RVEpiInterpY(:,1),SET(NO).RVEpiInterpY); - end; + end DATA.ViewIM{DATA.CurrentPanel} = []; %Clear data panel @@ -493,7 +509,7 @@ function extraslice_Callback(type) %#ok %Remove in systole basal slice SET(NO).EndoX(:,tf,1) = NaN; SET(NO).EndoY(:,tf,1) = NaN; - end; + end if ~isempty(SET(NO).EpiX) SET(NO).EpiX = cat(3,SET(NO).EpiX(:,:,1),SET(NO).EpiX); @@ -503,7 +519,7 @@ function extraslice_Callback(type) %#ok %Remove in systole basal slice SET(NO).EpiX(:,tf,1) = NaN; SET(NO).EpiY(:,tf,1) = NaN; - end; + end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoX = cat(3,SET(NO).RVEndoX(:,:,1),SET(NO).RVEndoX); @@ -512,7 +528,7 @@ function extraslice_Callback(type) %#ok SET(NO).RVEndoY(:,1,1) = SET(NO).RVEndoY(:,tf,2); SET(NO).RVEndoX(:,tf,1) = NaN; SET(NO).RVEndoY(:,tf,1) = NaN; - end; + end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiX = cat(3,SET(NO).RVEpiX(:,:,1),SET(NO).RVEpiX); @@ -522,7 +538,7 @@ function extraslice_Callback(type) %#ok %Remove in systole basal slice SET(NO).RVEpiX(:,tf,1) = NaN; SET(NO).RVEpiY(:,tf,1) = NaN; - end; + end %Draged (t*z) SET(NO).EndoDraged = cat(2,SET(NO).EndoDraged(:,1),SET(NO).EndoDraged); @@ -539,7 +555,7 @@ function extraslice_Callback(type) %#ok if numel(SET(NO).Scar.mthreshold) == SET(NO).ZSize SET(NO).Scar.mthreshold = cat(3,SET(NO).Scar.mthreshold(1),SET(NO).Scar.mthreshold); end - end; + end %MaR if not(isempty(SET(NO).MaR)) @@ -547,7 +563,7 @@ function extraslice_Callback(type) %#ok SET(NO).MaR.Result = cat(4,SET(NO).MaR.Result(:,:,:,1),SET(NO).MaR.Result); SET(NO).MaR.Manual = cat(4,SET(NO).MaR.Manual(:,:,:,1),SET(NO).MaR.Manual); SET(NO).MaR.MyocardMask = cat(4,SET(NO).MaR.MyocardMask(:,:,:,1),SET(NO).MaR.MyocardMask); - end; + end %ROI if SET(NO).RoiN > 0 @@ -582,59 +598,59 @@ function extraslice_Callback(type) %#ok if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinX = cat(2,SET(NO).EndoPinX,SET(NO).EndoPinX(:,end)); SET(NO).EndoPinY = cat(2,SET(NO).EndoPinY,SET(NO).EndoPinY(:,end)); - end; + end if ~isempty(SET(NO).EpiPinX) SET(NO).EpiPinY = cat(2,SET(NO).EpiPinY,SET(NO).EpiPinY(:,end)); SET(NO).EpiPinX = cat(2,SET(NO).EpiPinX,SET(NO).EpiPinX(:,end)); - end; + end if ~isempty(SET(NO).RVEndoPinX) SET(NO).RVEndoPinX = cat(2,SET(NO).RVEndoPinX,SET(NO).RVEndoPinX(:,end)); SET(NO).RVEndoPinY = cat(2,SET(NO).RVEndoPinY,SET(NO).RVEndoPinY(:,end)); - end; + end if ~isempty(SET(NO).RVEpiPinX) SET(NO).RVEpiPinY = cat(2,SET(NO).RVEpiPinY,SET(NO).RVEpiPinY(:,end)); SET(NO).RVEpiPinX = cat(2,SET(NO).RVEpiPinX,SET(NO).RVEpiPinX(:,end)); - end; + end if ~isempty(SET(NO).EndoInterpX) SET(NO).EndoInterpX = cat(2,SET(NO).EndoInterpX,SET(NO).EndoInterpX(:,end)); SET(NO).EndoInterpY = cat(2,SET(NO).EndoInterpY,SET(NO).EndoInterpY(:,end)); - end; + end if ~isempty(SET(NO).EpiInterpX) SET(NO).EpiInterpY = cat(2,SET(NO).EpiInterpY,SET(NO).EpiInterpY(:,end)); SET(NO).EpiInterpX = cat(2,SET(NO).EpiInterpX,SET(NO).EpiInterpX(:,end)); - end; + end if ~isempty(SET(NO).RVEndoInterpX) SET(NO).RVEndoInterpX = cat(2,SET(NO).RVEndoInterpX,SET(NO).RVEndoInterpX(:,end)); SET(NO).RVEndoInterpY = cat(2,SET(NO).RVEndoInterpY,SET(NO).RVEndoInterpY(:,end)); - end; + end if ~isempty(SET(NO).RVEpiInterpX) SET(NO).RVEpiInterpY = cat(2,SET(NO).RVEpiInterpY,SET(NO).RVInterpInterpY(:,end)); SET(NO).RVEpiInterpX = cat(2,SET(NO).RVEpiInterpX,SET(NO).RVInterpInterpX(:,end)); - end; + end DATA.ViewIM{DATA.CurrentPanel} = []; if ~isempty(SET(NO).EndoX) SET(NO).EndoX = cat(3,SET(NO).EndoX,SET(NO).EndoX(:,:,end)); SET(NO).EndoY = cat(3,SET(NO).EndoY,SET(NO).EndoY(:,:,end)); - end; + end if ~isempty(SET(NO).EpiX) SET(NO).EpiY = cat(3,SET(NO).EpiY,SET(NO).EpiY(:,:,end)); SET(NO).EpiX = cat(3,SET(NO).EpiX,SET(NO).EpiX(:,:,end)); - end; + end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoX = cat(3,SET(NO).RVEndoX,SET(NO).RVEndoX(:,:,end)); SET(NO).RVEndoY = cat(3,SET(NO).RVEndoY,SET(NO).RVEndoY(:,:,end)); - end; + end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiY = cat(3,SET(NO).RVEpiY,SET(NO).RVEpiY(:,:,end)); SET(NO).RVEpiX = cat(3,SET(NO).RVEpiX,SET(NO).RVEpiX(:,:,end)); - end; - + end + %Draged (t*z) SET(NO).EndoDraged = cat(2,SET(NO).EndoDraged,SET(NO).EndoDraged(:,1)); SET(NO).EpiDraged = cat(2,SET(NO).EpiDraged,SET(NO).EpiDraged(:,1)); @@ -650,7 +666,7 @@ function extraslice_Callback(type) %#ok if numel(SET(NO).Scar.mthreshold) == SET(NO).ZSize SET(NO).Scar.mthreshold = cat(3,SET(NO).Scar.mthreshold,SET(NO).Scar.mthreshold(end)); end - end; + end %Scar if not(isempty(SET(NO).MaR)) @@ -658,8 +674,8 @@ function extraslice_Callback(type) %#ok SET(NO).MaR.Result = cat(4,SET(NO).MaR.Result,SET(NO).MaR.Result(:,:,:,end)); SET(NO).MaR.Manual = cat(4,SET(NO).MaR.Manual,SET(NO).MaR.Manual(:,:,:,end)); SET(NO).MaR.MyocardMask = cat(4,SET(NO).MaR.MyocardMask,SET(NO).MaR.MyocardMask(:,:,:,end)); - end; -end; + end +end %remove Strain tagging analysis if not(isempty(SET(NO).StrainTagging)) @@ -670,8 +686,8 @@ function extraslice_Callback(type) %#ok SET(NO).StrainTagging = []; end -segment('updatemodeldisplay'); -segment('viewrefresh_Callback'); +%segment('viewrefresh_Callback'); +viewfunctions('setview') %---------------------------- function kspace_Callback %#ok @@ -690,10 +706,10 @@ function extraslice_Callback(type) %#ok f = fftshift(fft2(SET(NO).IM(:,:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice))); figure(123); -set(123,'NumberTitle','off','Name','K-space'); +set(123,'NumberTitle','off','Name',dprintf('K-space')); imagesc([-1 1],[-1 1],log(abs(f))); -xlabel('Normalized freq'); -ylabel('Normalized freq'); +xlabel(dprintf('Normalized freq')); +ylabel(dprintf('Normalized freq')); title('log(abs(fft(im)))'); %-------------------------------------- @@ -713,7 +729,7 @@ function extraslice_Callback(type) %#ok hold on; plot([0 1],[1 1],'k--'); plot([0 1],[0 0],'k--'); -title('Image intensity mapping'); +title(dprintf('Image intensity mapping')); axis([0 1 min(0,min(temp(:))) max(1,max(temp(:)))]) %--------------------------------------- @@ -731,23 +747,29 @@ function extraslice_Callback(type) %#ok else imagesc(2*SET(NO).VENC*(-0.5+temp)); set(gca,'clim',[-SET(NO).VENC SET(NO).VENC]); -end; +end colormap(jet); axis image off; colorbar; %-------------------------------------- -function duplicateimagestack_Callback %#ok +function duplicateimagestack_Callback(frompreviewmenu) %#ok %-------------------------------------- %Duplicates current image stack. This function breaks links to %linked datasets, parent and children. global DATA SET NO +if nargin>0 && frompreviewmenu %from context menu + dupno = segment_main('getclickedpreview'); +else + dupno = NO; +end + %Duplicate current dataset no = length(SET)+1; -SET(no) = SET(NO); +SET(no) = SET(dupno); SET(no).Linked = no; SET(no).Parent = []; @@ -756,13 +778,13 @@ function extraslice_Callback(type) %#ok if ~isempty(SET(no).Flow) || length(SET(no).Linked) > 1 mywarning('Image stack contains flow data and/or other stack links, not duplicating internal references.',DATA.GUI.Segment); SET(no).Flow = []; -end; +end -calcpreview = false; -drawfunctions('drawthumbnails',calcpreview); if ~strcmp(DATA.CurrentTheme,'3dp')% dont do switch if 3dp mode - segment('switchtoimagestack',no); + viewfunctions('setview',1,1,no,{'one'})%segment('switchtoimagestack',no); end +calcpreview = false; +drawfunctions('drawthumbnails',calcpreview); %----------------------------------------------- function upsampleimage_Callback(f,inputNO,silent) %#ok @@ -785,18 +807,18 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok if nargin==0 if not(yesno('Upsamle/Downsample image stack is not undoable, do you want to proceed?.',[],DATA.GUI.Segment)) return; - end; + end %Get factor [f,ok] = mygetnumber('Enter upsampling/downsampling factor (<1 => downsample)','Resampling Factor',2,0.001,10); if ~ok myfailed('Invalid factor or aborted.',DATA.GUI.Segment); return; - end; -end; + end +end if nargin<2 - inputNO=NO; + inputNO = NO; end if nargin<3 silent = false; @@ -805,7 +827,7 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok %Find image stacks to crop nos = SET(inputNO).Linked; %Crop current image stack -for no = nos; +for no = nos %Resample SET(no).IM = upsampleinplane(f,SET(no).IM,silent); @@ -820,70 +842,71 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok if ~isempty(SET(no).EndoX) SET(no).EndoX = resamplehelper(f,SET(no).EndoX); SET(no).EndoY = resamplehelper(f,SET(no).EndoY); - end; + end if ~isempty(SET(no).EpiX) SET(no).EpiX = resamplehelper(f,SET(no).EpiX); SET(no).EpiY = resamplehelper(f,SET(no).EpiY); - end; + end if ~isempty(SET(no).RVEndoX) SET(no).RVEndoX = resamplehelper(f,SET(no).RVEndoX); SET(no).RVEndoY = resamplehelper(f,SET(no).RVEndoY); - end; + end if ~isempty(SET(no).RVEpiX) SET(no).RVEpiX = resamplehelper(f,SET(no).RVEpiX); SET(no).RVEpiY = resamplehelper(f,SET(no).RVEpiY); - end; + end if ~isempty(SET(no).EndoPinX) SET(no).EndoPinX = resamplehelper(f,SET(no).EndoPinX); SET(no).EndoPinY = resamplehelper(f,SET(no).EndoPinY); - end; + end if ~isempty(SET(no).EpiPinX) SET(no).EpiPinX = resamplehelper(f,SET(no).EpiPinX); SET(no).EpiPinY = resamplehelper(f,SET(no).EpiPinY); - end; + end if ~isempty(SET(no).RVEndoPinX) SET(no).RVEndoPinX = resamplehelper(f,SET(no).RVEndoPinX); SET(no).RVEndoPinY = resamplehelper(f,SET(no).RVEndoPinY); - end; + end if ~isempty(SET(no).RVEpiPinX) SET(no).RVEpiPinX = resamplehelper(f,SET(no).RVEpiPinX); SET(no).RVEpiPinY = resamplehelper(f,SET(no).RVEpiPinY); - end; + end if ~isempty(SET(no).EndoInterpX) SET(no).EndoInterpX = resamplehelper(f,SET(no).EndoInterpX); SET(no).EndoInterpY = resamplehelper(f,SET(no).EndoInterpY); - end; + end if ~isempty(SET(no).EpiInterpX) SET(no).EpiInterpX = resamplehelper(f,SET(no).EpiInterpX); SET(no).EpiInterpY = resamplehelper(f,SET(no).EpiInterpY); - end; + end if ~isempty(SET(no).RVEndoInterpX) SET(no).RVEndoInterpX = resamplehelper(f,SET(no).RVEndoInterpX); SET(no).RVEndoInterpY = resamplehelper(f,SET(no).RVEndoInterpY); - end; + end if ~isempty(SET(no).RVEpiInterpX) SET(no).RVEpiInterpX = resamplehelper(f,SET(no).RVEpiInterpX); SET(no).RVEpiInterpY = resamplehelper(f,SET(no).RVEpiInterpY); - end; + end %Point if ~isempty(SET(no).Point) - SET(no).Point.X=resamplehelper(f,SET(no).Point.X); - SET(no).Point.Y=resamplehelper(f,SET(no).Point.Y); + SET(no).Point.X = resamplehelper(f,SET(no).Point.X); + SET(no).Point.Y = resamplehelper(f,SET(no).Point.Y); end + %Measurement if ~isempty(SET(no).Measure) for mloop=1:length(SET(no).Measure) - SET(no).Measure(mloop).X=resamplehelper(f,SET(no).Measure(mloop).X); - SET(no).Measure(mloop).Y=resamplehelper(f,SET(no).Measure(mloop).Y); + SET(no).Measure(mloop).X = resamplehelper(f,SET(no).Measure(mloop).X); + SET(no).Measure(mloop).Y = resamplehelper(f,SET(no).Measure(mloop).Y); end - end; - + end + %Resolution SET(no).ResolutionX = SET(no).ResolutionX/f; SET(no).ResolutionY = SET(no).ResolutionY/f; @@ -903,15 +926,7 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok SET(no).Roi(rloop).X = resamplehelper(f,SET(no).Roi(rloop).X); SET(no).Roi(rloop).Y = resamplehelper(f,SET(no).Roi(rloop).Y); end - - %CT LV center point - if isfield(SET(no),'CT') && isfield(SET(no).CT,'Apex') - SET(no).CT.AV(1) = resamplehelper(f,SET(no).CT.AV(1)); - SET(no).CT.AV(2) = resamplehelper(f,SET(no).CT.AV(2)); - SET(no).CT.Apex(1)= resamplehelper(f,SET(no).CT.Apex(1)); - SET(no).CT.Apex(2)= resamplehelper(f,SET(no).CT.Apex(2)); - end - + %Scar if not(isempty(SET(no).Scar)) SET(no).Scar.Auto = upsampleinplane(f,SET(no).Scar.Auto)>0.5; @@ -924,7 +939,7 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok if ~isempty(SET(no).Scar.GreyZone) SET(no).Scar.GreyZone.map = uint8(upsampleinplane(f,SET(no).Scar.GreyZone.map)); end - end; + end %MaR if not(isempty(SET(no).MaR)) @@ -933,14 +948,14 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok SET(no).MaR.Manual = int8(upsampleinplane(f,SET(no).MaR.Manual)); SET(no).MaR.Manual(SET(no).MaR.Manual<0) = int8(-1); SET(no).MaR.MyocardMask = upsampleinplane(f,SET(no).MaR.MyocardMask)>0.5; - end; + end %Phase correction if not(isempty(SET(no).Flow)) if not(isempty(SET(no).Flow.PhaseCorr)) SET(no).Flow.PhaseCorr = upsampleinplane(f,SET(no).Flow.PhaseCorr); - end; - end; + end + end %Zoom state SET(no).NormalZoomState = []; @@ -951,7 +966,7 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok SET(no).CurrentSlice = min(max(1,round(SET(no).CurrentSlice*f)),SET(no).ZSize); %Resample .LevelSet - if ~isempty(SET(no).LevelSet) + if strcmp(DATA.ProgramName,'Segment 3DPrint') && ~isempty(SET(no).LevelSet) %resample stored objects, important to resample stored object before %.BW since levelsetunpack uses the size of .BW and pack does not use @@ -959,34 +974,51 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok for obj=1:length(SET(no).LevelSet.Object.Ind) temp = segment3dp.tools('levelsetunpack',obj,no); if ~isempty(temp) - temp = upsamplevolume2([f,f,1,1],temp); + %temp = upsamplevolume2([f,f,1,1],temp,true); + temp = upsampleinplane(f,temp,silent); [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); - end; + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; + end end %resample .BW - SET(no).LevelSet.BW = uint8(squeeze(upsamplevolume2([f,f,1,1],SET(no).LevelSet.BW))); + SET(no).LevelSet.BW = upsampleinplane(f,SET(no).LevelSet.BW,silent); + %SET(no).LevelSet.BW = uint8(squeeze(upsamplevolume2([f,f,1,1],SET(no).LevelSet.BW,true))); %resample .Man - SET(no).LevelSet.Man = int8(squeeze(upsamplevolume2([f,f,1,1],SET(no).LevelSet.Man))); + DATA.LevelSet.Man = repmat(int8(0),size(SET(no).LevelSet.BW)); %size((squeeze(upsamplevolume2([f,f,1,1],SET(no).LevelSet.Man))); %---things to change %Zoomstate - SET(no).LevelSet.View.RZoomState=[]; - SET(no).LevelSet.View.GZoomState=[]; - SET(no).LevelSet.View.BZoomState=[]; + SET(no).LevelSet.View.RZoomState = []; + SET(no).LevelSet.View.GZoomState = []; + SET(no).LevelSet.View.BZoomState = []; %slice - SET(no).LevelSet.View.GSlice=max(1,min(round(resamplehelper(f,SET(no).LevelSet.View.GSlice)),SET(no).YSize)); - SET(no).LevelSet.View.BSlice=max(1,min(round(resamplehelper(f,SET(no).LevelSet.View.BSlice)),SET(no).XSize)); - + %slice + switch lower(DATA.LevelSet.imageorientation) + case 'transversal' + fieldy = 'GSlice'; + fieldx = 'BSlice'; + case 'sagittal' + fieldy = 'BSlice'; + fieldx = 'RSlice'; + case 'coronal' + fieldy = 'GSlice'; + fieldx = 'RSlice'; + end + + SET(no).LevelSet.View.(fieldx) = max(1,min(round(resamplehelper(f,SET(no).LevelSet.View.(fieldx))),SET(no).XSize)); + SET(no).LevelSet.View.(fieldy) = max(1,min(round(resamplehelper(f,SET(no).LevelSet.View.(fieldy))),SET(no).YSize)); + %resets zoom - segment('cleardatalevelset'); + cleardatalevelset segment3dp.tools('init3DP',1,1); %clear DATA.LevelSet %there is no sample dependent data in %data.levelset - %segment('cleardatalevelset'); + end %remove Strain tagging analysis @@ -1001,9 +1033,19 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok if isfield(SET(no),'RV') && ~isempty(SET(no).RV) && ~isempty(SET(no).RV.centerbasal) SET(no).RV.centerbasal = resamplehelper(f,SET(no).RV.centerbasal); SET(no).RV.centerapical = resamplehelper(f,SET(no).RV.centerapical); + end + + %CT LV reconstructions points + if ~isempty(SET(no).CT) + SET(no).CT.Apex(1)=min(size(SET(no).IM,1),max(1,round(resamplehelper(f,SET(no).CT.Apex(1))))); + SET(no).CT.Apex(2)=min(size(SET(no).IM,2),max(1,round(resamplehelper(f,SET(no).CT.Apex(2))))); + SET(no).CT.AV(1)=min(size(SET(no).IM,1),max(1,round(resamplehelper(f,SET(no).CT.AV(1))))); + SET(no).CT.AV(2)=min(size(SET(no).IM,2),max(1,round(resamplehelper(f,SET(no).CT.AV(2))))); + SET(no).CT.RVPulmi(1)=min(size(SET(no).IM,1),max(1,round(resamplehelper(f,SET(no).CT.RVPulmi(1))))); + SET(no).CT.RVPulmi(2)=min(size(SET(no).IM,2),max(1,round(resamplehelper(f,SET(no).CT.RVPulmi(2))))); end -end; +end DATA.EndoEDGE0 = []; DATA.EndoEDGE1 = []; @@ -1019,13 +1061,17 @@ function upsampleimage_Callback(f,inputNO,silent) %#ok [tf,loc] = ismember(nos,DATA.ViewPanels); [DATA.ViewIM{loc(tf)}] = deal([]); -segment('viewrefreshall_Callback'); +drawfunctions('drawno',no); +for p = loc(tf) + drawfunctions('drawselectedslice',p) + drawfunctions('drawselectedframe',p) +end +%viewfunctions('setview') % if nargin < 2 % if strcmp(DATA.CurrentTheme,'3dp') % segment3dp.tools('update3DP') % else -% segment('makeviewim',DATA.CurrentPanel,NO); -% segment('updatemodeldisplay'); +% DATA.ViewIM{DATA.CurrentPanel} = []; % drawfunctions('drawimageno'); % end % end @@ -1044,14 +1090,14 @@ function upsampletemporal_Callback(f) %#ok myfailed('Invalid upsampling/downsampling factor or aborted.',DATA.GUI.Segment); return; end -end; +end % check for still image forcecopy = false; if size(SET(NO).IM,3)==1 if ~yesno('Image has no temporal dimension. Do you want to proceed?') return - end; + end forcecopy = true; SET(NO).TimeVector = linspace(0,1,f); end @@ -1059,7 +1105,7 @@ function upsampletemporal_Callback(f) %#ok if not(isrectilinear(SET(NO).TimeVector)) if ~yesno(['Non uniform time steps detected. This is not '... 'supported for upsampling. Mean time step will be used ' ... - 'and time step information will be lost. Proceed?']); + 'and time step information will be lost. Proceed?']) return end end @@ -1081,7 +1127,7 @@ function upsampletemporal_Callback(f) %#ok nos = union(nos,nos); %Remove duplicates %Loop over image stacks. -for no = nos; +for no = nos if forcecopy || (SET(no).TSize>1) %Only upsample if timeresolved. Note linke stacks can have different %Number of timeframes (one if master have many as for instance in T2*) @@ -1099,42 +1145,42 @@ function upsampletemporal_Callback(f) %#ok else SET(no).TIncr = SET(no).TIncr*(oldtsize)/(newtsz); SET(no).TimeVector = SET(no).TIncr*(0:SET(no).TSize-1); - end; + end %--- Upsample volume %--- Upsample contour if ~isempty(SET(NO).EndoX) SET(no).EndoX = upsampletemporal(f,SET(no).EndoX); SET(no).EndoY = upsampletemporal(f,SET(no).EndoY); - end; + end if ~isempty(SET(NO).EpiX) SET(no).EpiX = upsampletemporal(f,SET(no).EpiX); SET(no).EpiY = upsampletemporal(f,SET(no).EpiY); - end; + end if ~isempty(SET(NO).RVEndoX) SET(no).RVEndoX = upsampletemporal(f,SET(no).RVEndoX); SET(no).RVEndoY = upsampletemporal(f,SET(no).RVEndoY); - end; + end if ~isempty(SET(NO).RVEpiX) SET(no).RVEpiX = upsampletemporal(f,SET(no).RVEpiX); SET(no).RVEpiY = upsampletemporal(f,SET(no).RVEpiY); - end; + end % The condition "no EndoXView/EpiXView" may be represented by a single NaN. if ~isempty(SET(NO).EndoXView) ... && ~(length(SET(NO).EndoXView) == 1 && all(isnan(SET(NO).EndoXView))) SET(no).EndoXView = upsampletemporal(f,SET(no).EndoXView); SET(no).EndoYView = upsampletemporal(f,SET(no).EndoYView); - end; + end if ~isempty(SET(NO).EpiXView) ... && ~(length(SET(NO).EpiXView) == 1 && all(isnan(SET(NO).EpiXView))) SET(no).EpiXView = upsampletemporal(f,SET(no).EpiXView); SET(no).EpiYView = upsampletemporal(f,SET(no).EpiYView); - end; + end SET(no).LVV = upsampletemporal(f,SET(no).LVV,'vector'); SET(no).PV = upsampletemporal(f,SET(no).PV,'vector'); @@ -1191,7 +1237,7 @@ function upsampletemporal_Callback(f) %#ok SET(no).Scar.MyocardMask = upsampletemporal(f,SET(no).Scar.MyocardMask); SET(no).Scar.NoReflow = upsampletemporal(f,SET(no).Scar.NoReflow); SET(no).Scar.IM = upsampletemporal(f,SET(no).Scar.IM); - end; + end %MaR if not(isempty(SET(no).MaR)) @@ -1200,7 +1246,7 @@ function upsampletemporal_Callback(f) %#ok SET(no).MaR.Manual = int8(upsampletemporal(f,single(SET(no).MaR.Manual))); SET(no).MaR.Manual(SET(no).MaR.Manual<0) = int8(-1); SET(no).MaR.MyocardMask = upsampletemporal(f,SET(no).MaR.MyocardMask); - end; + end %Reset zoomstate SET(no).NormalZoomState = []; @@ -1251,15 +1297,12 @@ function upsampletemporal_Callback(f) %#ok SET(no).StrainTagging = []; end - end; %If Tsize(loop)>1 -end; %Loop over image stacks + end %If Tsize(loop)>1 +end %Loop over image stacks segment('updatevolume'); DATA.ViewIM{DATA.CurrentPanel} = []; - -segment('makeviewim',DATA.CurrentPanel,NO); -segment('updatemodeldisplay'); -drawfunctions('drawimageno'); +drawfunctions('drawimages',DATA.CurrentPanel) %---------------------------------------- function newvol = upsampletemporal(f, vol, varargin) @@ -1281,7 +1324,7 @@ function upsampletemporal_Callback(f) %#ok type = 'segmentation'; else type = varargin{1}; -end; +end switch type case 'image' @@ -1359,18 +1402,18 @@ function upsampletemporal_Callback(f) %#ok for loop=1:size(vol,3) ZI = interp2(X,Y,vol(:,:,loop),XI,YI,interptype); newvol(:,:,loop) = ZI; - end; + end else %Simply duplicate newvol = repmat(vol,[1 round(f) 1]); - end; + end case 'vector' if isequal(length(vol),1) newvol = repmat(vol,1,round(f)); else newvol = interp1(1:length(vol),vol,linspace(1,length(vol),round(f*length(vol)))); - end; -end; + end +end %------------------------------------ function upsampleslices_Callback(f) %#ok @@ -1383,56 +1426,54 @@ function upsampleslices_Callback(f) %#ok if nargin==0 if not(yesno('Upsamle/Downsample slices is not undoable, do you want to proceed?.',[],DATA.GUI.Segment)) return; - end; + end %Get factor [f,ok] = mygetnumber('Enter upsampling/downsampling factor (<1 => downsample)','Resampling Factor',2,0,5); if ~ok myfailed('Invalid upsampling/downsampling factor or aborted.',DATA.GUI.Segment); return; - end; -end; - -% [imissingle,isint16] = classcheckim(NO);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants -% if not(imissingle) -% return; %question asked in classchekim -% end + end +end %Find image stacks to crop nos = SET(NO).Linked; %Crop current image stack -for no = nos; +for no = nos %--- Upsample volume - SET(no).IM = upsamplevolume2([1,1,1,f],SET(no).IM); + %SET(no).IM = upsamplevolume2([1,1,1,f],SET(no).IM,true); + cl = class(SET(no).IM); + SET(no).IM = feval(cl,upsampleslices(f,single(SET(no).IM),true)); + SET(no).ZSize = size(SET(no).IM,4); %--- Upsample contour if ~isempty(SET(NO).EndoX) SET(no).EndoX = upsampleslices(f,SET(no).EndoX); SET(no).EndoY = upsampleslices(f,SET(no).EndoY); - end; + end if ~isempty(SET(NO).EpiX) SET(no).EpiX = upsampleslices(f,SET(no).EpiX); SET(no).EpiY = upsampleslices(f,SET(no).EpiY); - end; + end if ~isempty(SET(NO).RVEndoX) SET(no).RVEndoX = upsampleslices(f,SET(no).RVEndoX); SET(no).RVEndoY = upsampleslices(f,SET(no).RVEndoY); - end; + end if ~isempty(SET(NO).RVEpiX) SET(no).RVEpiX = upsampleslices(f,SET(no).RVEpiX); SET(no).RVEpiY = upsampleslices(f,SET(no).RVEpiY); - end; + end %Point if ~isempty(SET(no).Point) SET(no).Point.Z=round(resamplehelper(f,SET(no).Point.Z)); - end - + end + %CurrentSlice SET(no).CurrentSlice=min(max(1,round(resamplehelper(f,SET(no).CurrentSlice))),SET(no).ZSize); @@ -1482,7 +1523,7 @@ function upsampleslices_Callback(f) %#ok SET(no).Scar.MyocardMask = upsampleslices(f,SET(no).Scar.MyocardMask); SET(no).Scar.NoReflow = upsampleslices(f,SET(no).Scar.NoReflow); SET(no).Scar.IM = upsampleslices(f,SET(no).Scar.IM); - end; + end %MaR if not(isempty(SET(no).MaR)) @@ -1491,7 +1532,7 @@ function upsampleslices_Callback(f) %#ok SET(no).MaR.Manual = int8(upsampleslices(f,single(SET(no).MaR.Manual))); SET(no).MaR.Manual(SET(no).MaR.Manual<0) = int8(-1); SET(no).MaR.MyocardMask = upsampleslices(f,SET(no).MaR.MyocardMask); - end; + end %Reset zoomstate SET(no).NormalZoomState = []; @@ -1499,7 +1540,7 @@ function upsampleslices_Callback(f) %#ok SET(no).MontageRowZoomState = []; %ROI's - for rloop=1:SET(no).RoiN + for rloop = 1:SET(no).RoiN SET(no).Roi(rloop).Z = min(max(1,round(f*SET(no).Roi(rloop).Z)),SET(no).ZSize); end @@ -1509,37 +1550,51 @@ function upsampleslices_Callback(f) %#ok %resample stored objects, important to resample stored object before %.BW since levelsetunpack uses the size of .BW and pack does not use %the size - for obj = 1:length(SET(no).LevelSet.Object.Ind) - temp = segment3dp.tools('levelsetunpack',obj,no); - temp = uint8(upsampleslices(f,single(temp))); - [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + for obj = 1:length(SET(no).LevelSet.Object.Ind) + temp = segment3dp.tools('levelsetunpack',obj,no); + temp = uint8(upsampleslices(f,single(temp))); + [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; end %The next two upsamples never have a time dimension - %resample .BW - SET(no).LevelSet.BW = uint8(squeeze(upsamplevolume2([1,1,f],single(SET(no).LevelSet.BW)))); - - %resample .Man - SET(no).LevelSet.Man = int8(squeeze(upsamplevolume2([1,1,f],single(SET(no).LevelSet.Man)))); - - %---things to change + %resample .BW + SET(no).LevelSet.BW = uint8(squeeze(upsamplevolume2([1,1,f],single(SET(no).LevelSet.BW),true))); - %Zoomstate - SET(no).LevelSet.View.RZoomState=[]; - SET(no).LevelSet.View.GZoomState=[]; - SET(no).LevelSet.View.BZoomState=[]; - - %slice - if SET(no).ZSize>1 - SET(no).LevelSet.View.RSlice = max(1,min(round(resamplehelper(f,SET(no).LevelSet.View.RSlice)),SET(no).ZSize)); - else - SET(no).LevelSet.View.RSlice = max(1,min(round(resamplehelper(f,SET(no).LevelSet.View.RSlice)),SET(no).TSize)); + %resample .Man + DATA.LevelSet.Man = repmat(int8(0),size(SET(no).LevelSet.BW)); %squeeze(upsamplevolume2([1,1,f],single(SET(no).LevelSet.Man)))); + + %---things to change + + %Zoomstate + SET(no).LevelSet.View.RZoomState=[]; + SET(no).LevelSet.View.GZoomState=[]; + SET(no).LevelSet.View.BZoomState=[]; + + %slice + if ~isfield(DATA.LevelSet,'imageorientation') + DATA.LevelSet.imageorientation = 'transversal'; + end + + switch lower(DATA.LevelSet.imageorientation) + case 'transversal' + field = 'RSlice'; + slice = SET(no).LevelSet.View.RSlice; + case 'sagittal' + field = 'GSlice'; + slice = SET(no).LevelSet.View.GSlice; + case 'coronal' + field = 'BSlice'; + slice = SET(no).LevelSet.View.BSlice; end - %segment('cleardatalevelset'); + SET(no).LevelSet.View.(field)= max(1,min(round(resamplehelper(f,slice)),SET(no).ZSize)); + + %cleardatalevelset %segment3dp.tools('levelsetreset',no) %clear DATA.LevelSet - segment('cleardatalevelset'); + cleardatalevelset segment3dp.tools('init3DP',1,1); end @@ -1555,9 +1610,16 @@ function upsampleslices_Callback(f) %#ok if isfield(SET(no),'RV') && ~isempty(SET(no).RV) && ~isempty(SET(no).RV.slicebasal) SET(no).RV.slicebasal = max(1,min(round(resamplehelper(f,SET(no).RV.slicebasal)),SET(no).ZSize)); SET(no).RV.sliceapical = max(1,min(round(resamplehelper(f,SET(no).RV.sliceapical)),SET(no).ZSize)); - end + end + + %CT LV reconstructions points + if ~isempty(SET(no).CT)&&isfield(SET(no).CT,'Apex') + SET(no).CT.Apex(3)=min(size(SET(no).IM,4),max(1,round(resamplehelper(f,SET(no).CT.Apex(3))))); + SET(no).CT.AV(3)=min(size(SET(no).IM,4),max(1,round(resamplehelper(f,SET(no).CT.AV(3))))); + SET(no).CT.RVPulmi(3)=min(size(SET(no).IM,4),max(1,round(resamplehelper(f,SET(no).CT.RVPulmi(3))))); + end -end; %Loop over image stacks +end %Loop over image stacks %make sure not out of bounds. SET(no).CurrentSlice = 1; @@ -1566,12 +1628,9 @@ function upsampleslices_Callback(f) %#ok DATA.ViewIM{DATA.CurrentPanel} = []; -% segment('makeviewim',DATA.CurrentPanel,NO); -% segment('updatemodeldisplay'); +% DATA.ViewIM{DATA.CurrentPanel} = []; % drawfunctions('drawimageno'); - segment('viewrefreshall_Callback') - updatetool - + viewfunctions('setview'); %---------------------------------- function setimageinfo_Callback(arg) @@ -1588,7 +1647,7 @@ function setimageinfo_Callback(arg) if not(DATA.DataLoaded) return; -end; +end gui = DATA.GUI.SetImageInfo; @@ -1597,7 +1656,7 @@ function setimageinfo_Callback(arg) if nargin < 1 arg = 'init'; end -end; +end switch arg case 'init' @@ -1629,14 +1688,14 @@ function setimageinfo_Callback(arg) if not(isnan(tincr)) heartrate = round(60/(tincr*SET(gui.no).TSize)); set(gui.handles.heartrateedit,'String',heartrate); - end; + end case 'heartrateedit' hr = mygetedit(gui.handles.heartrateedit); hr = str2double(hr); if not(isnan(hr)) tincr = (60/hr)/SET(gui.no).TSize; set(gui.handles.timeincrementedit,'String',tincr*1000); - end; + end case 'rotatedyes' set(gui.handles.rotatedyesradiobutton,'Value',1); set(gui.handles.rotatednoradiobutton,'Value',0); @@ -1649,23 +1708,23 @@ function setimageinfo_Callback(arg) if str2double(get(gui.handles.slicethicknessedit,'String'))<=0 myfailed('Slice thickness must be positive.',DATA.GUI.Segment); ok = false; - end; + end if str2double(get(gui.handles.resolutionxedit,'String'))<=0 myfailed('X Resolution must be positive.',DATA.GUI.Segment); ok = false; - end; + end if str2double(get(gui.handles.resolutionyedit,'String'))<=0 myfailed('Y Resolution must be positive.',DATA.GUI.Segment); ok = false; - end; + end if str2double(get(gui.handles.timeincrementedit,'String'))<0 myfailed('Time increment must be positive.',DATA.GUI.Segment); ok = false; - end; + end if str2double(get(gui.handles.heartrateedit,'String'))<0 myfailed('Heart rate must be positive.',DATA.GUI.Segment); ok = false; - end; + end if ok if ~isempty(SET(gui.no).Flow) && (SET(gui.no).Flow.MagnitudeNo==gui.no || SET(gui.no).Flow.PhaseNo==gui.no) @@ -1684,7 +1743,11 @@ function setimageinfo_Callback(arg) SET(no2).TIncr = str2double(get(gui.handles.timeincrementedit,'String'))/1000; SET(no2).TimeVector = linspace(0,(SET(gui.no).TSize-1)*SET(gui.no).TIncr,SET(gui.no).TSize); SET(no2).BeatTime = SET(gui.no).TIncr*SET(gui.no).TSize; - SET(no2).HeartRate = round(str2double(get(gui.handles.heartrateedit,'String'))); + hr = str2double(get(gui.handles.heartrateedit,'String')); + SET(no2).HeartRate = hr; + if not(isempty(SET(no2).Flow)) && isfield(SET(no2).Flow,'HeartRate') + SET(no2).Flow.HeartRate = hr; + end if get(gui.handles.rotatedyesradiobutton,'Value') SET(no2).Rotated = true; else @@ -1696,10 +1759,10 @@ function setimageinfo_Callback(arg) SET(gui.no).NormalZoomState = []; SET(gui.no).MontageZoomState = []; SET(gui.no).MontageRowZoomState = []; - segment('viewrefresh_Callback'); + viewfunctions('setview') if length(nos)>1 - mymsgbox(sprintf('Information applied to image stacks %d, %d.',nos(1),nos(2)),'Done!',DATA.GUI.Segment); + mymsgbox(dprintf('Information applied to image stacks %d, %d.',nos(1),nos(2)),'Done!',DATA.GUI.Segment); else mymsgbox('Information applied to current image stack.','Done!',DATA.GUI.Segment); end @@ -1712,7 +1775,7 @@ function setimageinfo_Callback(arg) DATA.GUI.SetImageInfo = close(DATA.GUI.SetImageInfo); catch %#ok delete(gui.fig); - end; + end otherwise myfailed(dprintf('Unknown argument %s to Set image info',arg),DATA.GUI.Segment); return; @@ -1722,24 +1785,23 @@ function setimageinfo_Callback(arg) function imageinfo_Callback(arg) %#ok %------------------------------- %Displays image information of current image stack + global DATA SET NO persistent handles if nargin==0 - set(DATA.Handles.imageinfoicon,'state','off'); - if not(DATA.DataLoaded) return; - end; - - fig = openfig('imageinfo.fig','reuse'); - myadjust(fig,DATA.GUI.Segment); - set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); + end + fig = mygui('imageinfo.fig'); % Generate a structure of handles to pass to callbacks, and store it. - handles = guihandles(fig); - handles.fig=fig; - + handles = fig.handles; + handles.fig = handles.figure1; + %ensure translated + set(handles.closepushbutton,'String',dprintf('Close')); + set(handles.titleuipanel,'Title',dprintf('Image Info')); + stri = [... sprintf('FileName: %s\n',SET(NO).FileName),... sprintf('OrigFileName: %s\n',SET(NO).OrigFileName),... @@ -1756,7 +1818,8 @@ function imageinfo_Callback(arg) %#ok sprintf('AccessionNumber: %s\n',SET(NO).AccessionNumber),... sprintf('StudyUID: %s\n',SET(NO).StudyUID),... sprintf('StudyID: %s\n',SET(NO).StudyID),... - sprintf('EchoTime: %0.5g [ms]\n',SET(NO).EchoTime),... + sprintf('SeriesNumber: %d\n',SET(NO).SeriesNumber),... + sprintf('EchoTime: %0.5g [ms]\n',SET(NO).EchoTime(1)),... sprintf('RepetitionTime: %0.5g [ms]\n',SET(NO).RepetitionTime),... sprintf('InversionTime(mean): %0.5g [ms]\n',mean(SET(NO).InversionTime(:))),... sprintf('HeartRate: %0.5g\n',SET(NO).HeartRate),... @@ -1807,9 +1870,9 @@ function imageinfo_Callback(arg) %#ok %Remove all timeframes in current image stack except diastole and systole. global DATA SET NO -if ~yesno('Removing all timeframes but diastole and systole (not undoable). Are you sure?',[],DATA.GUI.Segment); +if ~yesno('Removing all timeframes but diastole and systole (not undoable). Are you sure?',[],DATA.GUI.Segment) return; -end; +end ind = false(1,SET(NO).TSize); ind(SET(NO).EDT) = true; @@ -1822,9 +1885,9 @@ function imageinfo_Callback(arg) %#ok %Remove all timeframes except current timeframe. global DATA SET NO -if ~yesno('Removing all but this timeframe (not undoable). Are you sure?',[],DATA.GUI.Segment); +if ~yesno('Removing all but this timeframe (not undoable). Are you sure?',[],DATA.GUI.Segment) return; -end; +end ind = ((1:SET(NO).TSize)==SET(NO).CurrentTimeFrame); removetimeframes(ind); @@ -1835,13 +1898,14 @@ function imageinfo_Callback(arg) %#ok %Remove current timeframe global DATA SET NO -if ~yesno('Removing current timeframe (not undoable). Are you sure?',[],DATA.GUI.Segment); +if ~yesno('Removing current timeframe (not undoable). Are you sure?',[],DATA.GUI.Segment) return; -end; +end ind = ((1:SET(NO).TSize)~=SET(NO).CurrentTimeFrame); removetimeframes(ind); + %------------------------------------------ function removenexttimeframes_Callback %#ok %------------------------------------------ @@ -1851,16 +1915,16 @@ function imageinfo_Callback(arg) %#ok if SET(NO).TSize==1 myfailed('Only one timeframe exists. Can not remove current timeframe.',DATA.GUI.Segment); return; -end; +end if SET(NO).CurrentTimeFrame==SET(NO).TSize myfailed('Last timeframe. No more timeframes to delete.',DATA.GUI.Segment); return; -end; +end -if ~yesno('Removing next timeframe and all timeframes to last timeframe. Are you sure?',[],DATA.GUI.Segment); +if ~yesno('Removing next timeframe and all timeframes to last timeframe. Are you sure?',[],DATA.GUI.Segment) return; -end; +end ind = true(1,SET(NO).TSize); ind((SET(NO).CurrentTimeFrame+1):end) = false; @@ -1875,11 +1939,11 @@ function imageinfo_Callback(arg) %#ok if SET(NO).TSize==1 myfailed('Only one timeframe exists. Can not remove current timeframe.',DATA.GUI.Segment); return; -end; +end -if ~yesno('Removing timeframes from start up to previous timeframe. Are you sure?',[],DATA.GUI.Segment); +if ~yesno('Removing timeframes from start up to previous timeframe. Are you sure?',[],DATA.GUI.Segment) return; -end; +end ind = true(1,SET(NO).TSize); ind(1:(SET(NO).CurrentTimeFrame-1)) = false; @@ -1901,19 +1965,19 @@ function removetimeframes(ind) DATA.EndoEDGE1 = DATA.EndoEDGE1(:,:,ind,:); DATA.EndoEDGE2 = DATA.EndoEDGE2(:,:,ind,:); DATA.EndoEDGE3 = DATA.EndoEDGE3(:,:,ind,:); -end; +end if DATA.EpiEdgeDetected DATA.EpiEDGE0 = DATA.EpiEDGE0(:,:,ind,:); DATA.EpiEDGE1 = DATA.EpiEDGE1(:,:,ind,:); DATA.EpiEDGE2 = DATA.EpiEDGE2(:,:,ind,:); DATA.EpiEDGE3 = DATA.EpiEDGE3(:,:,ind,:); -end; +end nop = SET(NO).Linked; for loop = 1:length(DATA.ViewIM) DATA.ViewIM{loop} = []; -end; +end %Loop over imagestacks for nloop=1:length(nop) @@ -1935,6 +1999,11 @@ function removetimeframes(ind) SET(no).TimeVector = SET(no).TimeVector(ind); end + if isfield(SET(no),'TriggerTime') && numel(SET(no).TriggerTime)>1 + %TriggerTime + SET(no).TriggerTime=SET(no).TriggerTime(:,ind); + end + if numel(SET(no).InversionTime)>1 %InversionTime SET(no).InversionTime = SET(no).InversionTime(:,ind); @@ -1967,7 +2036,7 @@ function removetimeframes(ind) else SET(no).EST=newEST; SET(no).EDT=newEDT; - end; + end SET(no).LVV = SET(no).LVV(ind); SET(no).EPV = SET(no).EPV(ind); @@ -1978,59 +2047,59 @@ function removetimeframes(ind) if ~isempty(SET(no).EndoX) SET(no).EndoX = SET(no).EndoX(:,ind,:); SET(no).EndoY = SET(no).EndoY(:,ind,:); - end; + end if ~isempty(SET(no).EpiX) SET(no).EpiX = SET(no).EpiX(:,ind,:); SET(no).EpiY = SET(no).EpiY(:,ind,:); - end; + end if ~isempty(SET(no).RVEndoX) SET(no).RVEndoX = SET(no).RVEndoX(:,ind,:); SET(no).RVEndoY = SET(no).RVEndoY(:,ind,:); - end; + end if ~isempty(SET(no).RVEpiX) SET(no).RVEpiX = SET(no).RVEpiX(:,ind,:); SET(no).RVEpiY = SET(no).RVEpiY(:,ind,:); - end; + end if ~isempty(SET(no).EndoPinX) SET(no).EndoPinX = SET(no).EndoPinX(ind,:); SET(no).EndoPinY = SET(no).EndoPinY(ind,:); - end; + end if ~isempty(SET(no).EpiPinX) SET(no).EpiPinX = SET(no).EpiPinX(ind,:); SET(no).EpiPinY = SET(no).EpiPinY(ind,:); - end; + end if ~isempty(SET(no).RVEndoPinX) SET(no).RVEndoPinX = SET(no).RVEndoPinX(ind,:); SET(no).RVEndoPinY = SET(no).RVEndoPinY(ind,:); - end; + end if ~isempty(SET(no).RVEpiPinX) SET(no).RVEpiPinX = SET(no).RVEpiPinX(ind,:); SET(no).RVEpiPinY = SET(no).RVEpiPinY(ind,:); - end; + end if ~isempty(SET(no).EndoInterpX) SET(no).EndoInterpX = SET(no).EndoInterpX(ind,:); SET(no).EndoInterpY = SET(no).EndoInterpY(ind,:); - end; + end if ~isempty(SET(no).EpiInterpX) SET(no).EpiInterpX = SET(no).EpiInterpX(ind,:); SET(no).EpiInterpY = SET(no).EpiInterpY(ind,:); - end; + end if ~isempty(SET(no).RVEndoInterpX) SET(no).RVEndoInterpX = SET(no).RVEndoInterpX(ind,:); SET(no).RVEndoInterpY = SET(no).RVEndoInterpY(ind,:); - end; + end if ~isempty(SET(no).RVEpiInterpX) SET(no).RVEpiInterpX = SET(no).RVEpiInterpX(ind,:); SET(no).RVEpiInterpY = SET(no).RVEpiInterpY(ind,:); - end; + end if ~isempty(SET(no).EndoDraged) SET(no).EndoDraged = SET(no).EndoDraged(ind,:); - end; + end if ~isempty(SET(no).EpiDraged) SET(no).EpiDraged = SET(no).EpiDraged(ind,:); - end; + end if SET(no).RoiN>0 for rloop=1:SET(no).RoiN @@ -2038,21 +2107,21 @@ function removetimeframes(ind) SET(no).Roi(rloop).Y = SET(no).Roi(rloop).Y(:,ind); SET(no).Roi(rloop).T = find(not(isnan(SET(no).Roi(rloop).X(1,:)))); end - end; + end SET(no).TSize = size(SET(no).IM,3); else mywarning('Cannot delete current timeframe when there is only one timeframe.',DATA.GUI.Segment); - end; + end if SET(no).EndAnalysis>SET(no).TSize SET(no).EndAnalysis = SET(no).TSize; - end; + end if SET(no).StartAnalysis>SET(no).TSize SET(no).StartAnalysis = SET(no).TSize; - end; + end SET(no).CurrentTimeFrame = min(SET(no).CurrentTimeFrame,SET(no).TSize); @@ -2066,13 +2135,15 @@ function removetimeframes(ind) temp=segment3dp.tools('levelsetunpack',obj,no); temp=temp(:,:,ind,:); [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; end %crop .BW - SET(no).LevelSet.BW=SET(NO).LevelSet.BW(:,:,ind,:); + SET(no).LevelSet.BW = SET(NO).LevelSet.BW(:,:,ind,:); %crop .Man - SET(no).LevelSet.Man=SET(NO).LevelSet.Man(:,:,ind,:); + DATA.LevelSet.Man = 0*SET(no).LevelSet.BW; %SET(NO).LevelSet.Man(:,:,ind,:); %---things to change @@ -2085,7 +2156,7 @@ function removetimeframes(ind) SET(no).LevelSet.View.TSlice=round(SET(no).TSize/2); %clear DATA.LevelSet - segment('cleardatalevelset'); + cleardatalevelset end %MaR @@ -2095,7 +2166,7 @@ function removetimeframes(ind) SET(no).MaR.Manual = SET(no).MaR.Manual(:,:,ind,:); SET(no).MaR.MyocardMask = SET(no).MaR.MyocardMask(:,:,ind,:); SET(no).MaR.Percentage = SET(no).MaR.Percentage(ind); - end; + end % remove measures indi=find(ind); @@ -2137,15 +2208,15 @@ function removetimeframes(ind) SET(no).StrainTagging = []; end -end; %Loop over all linked image stacks. +end %Loop over all linked image stacks. if ~DATA.Silent mymsgbox(dprintf('Removed timeframe(s) %s.',num2str(find(not(ind)))),'',DATA.GUI.Segment); -end; +end -segment('updatemodeldisplay'); -drawfunctions('drawimageno'); +drawfunctions('drawpanel',DATA.CurrentPanel); segment('updatevolume'); +DATA.updatetimebaraxes; % With disabletimethings commented out, this does nothing, % so I commented out the whole if statement /JU @@ -2193,15 +2264,19 @@ function removetimeframes(ind) removeslices_Callback(ind); %end; -%--------------------------------- -function removesliceshelper(ind) -%--------------------------------- +%------------------------------------- +function removesliceshelper(ind,newno) +%------------------------------------- %This is the workhorse when removing slices ind is a logical input of which %slices to keep. global DATA SET NO +if nargin<2 + newno = NO; +end + %Used for ROI removal -oldslices = 1:SET(NO).ZSize; +oldslices = 1:SET(newno).ZSize; slicemap = oldslices; slicemap(not(ind)) = NaN; slicemap(ind) = 1:sum(ind); @@ -2211,25 +2286,25 @@ function removesliceshelper(ind) DATA.EndoEDGE1 = DATA.EndoEDGE1(:,:,:,ind); DATA.EndoEDGE2 = DATA.EndoEDGE2(:,:,:,ind); DATA.EndoEDGE3 = DATA.EndoEDGE3(:,:,:,ind); -end; +end if not(isempty(DATA.BALLOON)) DATA.BALLOON = DATA.BALLOON(:,:,:,ind); -end; +end if DATA.EpiEdgeDetected DATA.EpiEDGE0 = DATA.EpiEDGE0(:,:,:,ind); DATA.EpiEDGE1 = DATA.EpiEDGE1(:,:,:,ind); DATA.EpiEDGE2 = DATA.EpiEDGE2(:,:,:,ind); DATA.EpiEDGE3 = DATA.EpiEDGE3(:,:,:,ind); -end; +end %Find image stacks to crop -nop = SET(NO).Linked; %Crop current and linked image stacks -if ~isempty(SET(NO).Parent) - no = SET(NO).Parent; +nop = SET(newno).Linked; %Crop current and linked image stacks +if ~isempty(SET(newno).Parent) + no = SET(newno).Parent; else - no = NO; + no = newno; end %---- Loop over image stacks for Flow-y data, @@ -2255,7 +2330,9 @@ function removesliceshelper(ind) slicedistance = SET(nol).SliceThickness + SET(nol).SliceGap; SET(nol).ImagePosition = SET(nol).ImagePosition - slicestoshift*zdir*slicedistance; - end; + SET(nol).RotatedImagePosition = SET(nol).RotatedImagePosition - slicestoshift*zdir*slicedistance; + + end %PapillaryIM if not(isempty(SET(nol).PapillaryIM)) @@ -2276,7 +2353,7 @@ function removesliceshelper(ind) if numel(SET(no).Scar.mthreshold) == SET(no).ZSize SET(no).Scar.mthreshold = SET(no).Scar.mthreshold(ind); end -end; +end %MaR if not(isempty(SET(no).MaR)) @@ -2284,7 +2361,7 @@ function removesliceshelper(ind) SET(no).MaR.Result = SET(no).MaR.Result(:,:,:,ind); SET(no).MaR.Manual = SET(no).MaR.Manual(:,:,:,ind); SET(no).MaR.MyocardMask = SET(no).MaR.MyocardMask(:,:,:,ind); -end; +end %CT definition of slices included in LV if isfield(SET(no),'CT') && isfield(SET(no).CT,'Apex') @@ -2303,56 +2380,56 @@ function removesliceshelper(ind) if ~isempty(SET(no).EndoX) SET(no).EndoX = SET(no).EndoX(:,:,ind); SET(no).EndoY = SET(no).EndoY(:,:,ind); -end; +end if ~isempty(SET(no).EpiX) SET(no).EpiX = SET(no).EpiX(:,:,ind); SET(no).EpiY = SET(no).EpiY(:,:,ind); -end; +end if ~isempty(SET(no).RVEndoX) SET(no).RVEndoX = SET(no).RVEndoX(:,:,ind); SET(no).RVEndoY = SET(no).RVEndoY(:,:,ind); -end; +end - if ~isempty(SET(no).RVEpiX) +if ~isempty(SET(no).RVEpiX) SET(no).RVEpiX = SET(no).RVEpiX(:,:,ind); SET(no).RVEpiY = SET(no).RVEpiY(:,:,ind); -end; +end if ~isempty(SET(no).EndoPinX) SET(no).EndoPinX = SET(no).EndoPinX(:,ind); SET(no).EndoPinY = SET(no).EndoPinY(:,ind); -end; +end if ~isempty(SET(no).EpiPinX) SET(no).EpiPinX = SET(no).EpiPinX(:,ind); SET(no).EpiPinY = SET(no).EpiPinY(:,ind); -end; +end if ~isempty(SET(no).RVEndoPinX) SET(no).RVEndoPinX = SET(no).RVEndoPinX(:,ind); SET(no).RVEndoPinY = SET(no).RVEndoPinY(:,ind); -end; +end if ~isempty(SET(no).RVEpiPinX) SET(no).RVEpiPinX = SET(no).RVEpiPinX(:,ind); SET(no).RVEpiPinY = SET(no).RVEpiPinY(:,ind); -end; +end if ~isempty(SET(no).EndoInterpX) SET(no).EndoInterpX = SET(no).EndoInterpX(:,ind); SET(no).EndoInterpY = SET(no).EndoInterpY(:,ind); -end; +end if ~isempty(SET(no).EpiInterpX) SET(no).EpiInterpX = SET(no).EpiInterpX(:,ind); SET(no).EpiInterpY = SET(no).EpiInterpY(:,ind); -end; +end if ~isempty(SET(no).RVEndoInterpX) SET(no).RVEndoInterpX = SET(no).RVEndoInterpX(:,ind); SET(no).RVEndoInterpY = SET(no).RVEndoInterpY(:,ind); -end; +end if ~isempty(SET(no).RVEpiInterpX) SET(no).RVEpiInterpX = SET(no).RVEpiInterpX(:,ind); SET(no).RVEpiInterpY = SET(no).RVEpiInterpY(:,ind); -end; +end SET(no).EndoDraged = SET(no).EndoDraged(:,ind); SET(no).EpiDraged = SET(no).EpiDraged(:,ind); @@ -2364,7 +2441,7 @@ function removesliceshelper(ind) SET(no).Roi(loop).Z = slicemap(SET(no).Roi(loop).Z); roiind(loop)=1; end -end; +end roiind=logical(roiind); %Remove ROI's (if necessary) @@ -2377,36 +2454,40 @@ function removesliceshelper(ind) if not(isempty(SET(no).Scar)) segment('updatevolume'); viability('viabilitycalcvolume'); -end; +end %remove slices in .LevelSet -if ~isempty(SET(no).LevelSet) +if ~isempty(SET(no).LevelSet) && isfield(SET(no).LevelSet,'Object') %remove slices in stored objects, important to do this in stored object before %.BW since levelsetunpack uses the size of .BW and pack does not use %the size - for obj=1:length(SET(no).LevelSet.Object.Ind) + for obj=1:length(SET(no).LevelSet.Object.Ind) if ndims(SET(no).LevelSet.BW)>3 %Support both old and new levelset temp = segment3dp.tools('levelsetunpack',obj,no); temp = temp(:,:,:,ind); [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; else temp = segment3dp.tools('levelsetunpack',obj,no); temp = temp(:,:,ind); [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); - end; + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; + end end %crop .BW & Man if ndims(SET(no).LevelSet.BW)>3 - SET(no).LevelSet.BW=SET(NO).LevelSet.BW(:,:,:,ind); - SET(no).LevelSet.Man=SET(NO).LevelSet.Man(:,:,:,ind); + SET(no).LevelSet.BW = SET(NO).LevelSet.BW(:,:,:,ind); %never run currently + DATA.LevelSet.Man = 0*SET(no).LevelSet.BW; %SET(NO).LevelSet.Man(:,:,:,ind); else - SET(no).LevelSet.BW=SET(NO).LevelSet.BW(:,:,ind); - SET(no).LevelSet.Man=SET(NO).LevelSet.Man(:,:,ind); - end; + SET(no).LevelSet.BW = SET(NO).LevelSet.BW(:,:,ind); + DATA.LevelSet.Man = 0*SET(no).LevelSet.BW; %SET(NO).LevelSet.Man(:,:,ind); + end %---things to change @@ -2423,16 +2504,16 @@ function removesliceshelper(ind) end %clear DATA.LevelSet - segment('cleardatalevelset'); + cleardatalevelset end if ~isempty(SET(no).Point.X) - pointind = not(isnan(slicemap(SET(no).Point.Z))); + pointind = not(isnan(slicemap(round(SET(no).Point.Z)))); for loop=1:length(SET(no).Point.X) - if not(isnan(slicemap(SET(no).Point.Z(loop)))) - SET(no).Point.Z(loop) = slicemap(SET(no).Point.Z(loop)); - end; - end; + if not(isnan(slicemap(round(SET(no).Point.Z(loop))))) + SET(no).Point.Z(loop) = slicemap(round(SET(no).Point.Z(loop))); + end + end %Remove points if necessary SET(no).Point.X = SET(no).Point.X(pointind); @@ -2440,7 +2521,7 @@ function removesliceshelper(ind) SET(no).Point.T = SET(no).Point.T(pointind); SET(no).Point.Z = SET(no).Point.Z(pointind); SET(no).Point.Label = SET(no).Point.Label(pointind); -end; +end % remove measures if ~isempty(SET(no).Measure) @@ -2492,211 +2573,53 @@ function removeslices_Callback(ind) %Generate index ind = true(SET(NO).ZSize,1); ind(SET(NO).StartSlice:SET(NO).EndSlice)=false; -end; +end if ~any(ind) myfailed('If you do this there will be no slices left!',DATA.GUI.Segment); return; -end; +end if nargin~=2 - if ~yesno('Do you really want to remove the selected slices? This operation is not undoable',[],DATA.GUI.Segment); + if ~yesno('Do you really want to remove the selected slices? This operation is not undoable',[],DATA.GUI.Segment) DATA.failedaborted; return; - end; -end; + end +end if ~isempty(SET(NO).LevelSet) && length(ind)==1 && SET(NO).TSize==1 - if ~yesno('Image stack contains general segmentation tool data. This will be lost since only 2D image will be left after this operation . Are you sure?',[],DATA.GUI.Segment); + if ~yesno('Image stack contains general segmentation tool data. This will be lost since only 2D image will be left after this operation . Are you sure?',[],DATA.GUI.Segment) DATA.failedaborted; return; - end; + end SET(NO).LevelSet = []; -end; +end if ind(1)&&ind(end)&&(sum(~ind)>0) %take first and last and remove som in between => image position will %fail. - if ~yesno('This operation will make the 3D data inconsistent. Do you want to proceed?',[],DATA.GUI.Segment); + if ~yesno('This operation will make the 3D data inconsistent. Do you want to proceed?',[],DATA.GUI.Segment) DATA.failedaborted; return; - end; -end; + end +end removesliceshelper(ind); %Call to remove -segment('updatemodeldisplay'); segment('updatevolume'); DATA.ViewIM{DATA.CurrentPanel} = []; if SET(NO).ZSize<20 - segment('viewimage_Callback','montage'); + viewfunctions('setviewtype','montage') else - segment('viewimage_Callback','one'); -end; -segment('viewrefresh_Callback'); - -%----------------------------------- -function crop_Buttondown(panel) %#ok -%----------------------------------- -%Buttondown function to crop the image stack -global DATA SET NO - -killbuttondown = segment('switchtopanel',panel); - -if killbuttondown - return -end - -if isequal(DATA.CurrentTool,'select') - return; -end - -if isfield(SET(NO).StrainTagging,'runningregistration') && SET(NO).StrainTagging.runningregistration - myfailed('Can not crop while registration is running.',DATA.GUI.Segment); - return; -end - -if isequal(DATA.ViewPanelsType{DATA.CurrentPanel},'mmodetemporal') - myfailed('Can not crop in mmode temporal view.',DATA.GUI.Segment); - return; -end; - -[x,y,slice] = segment('getclickedcoords'); -if (slice>SET(NO).ZSize) - return; -end -segment('switchtoslice',slice); - -%Check what type of click -switch get(DATA.imagefig,'SelectionType') - case 'normal' - %Setup - - if ismember(DATA.ViewPanelsType{panel},{'montage','montagerow','montagefit','sax3'}) - c = 1+mod(slice-1,DATA.ViewPanelsMatrix{panel}(2)); - r = ceil(slice/DATA.ViewPanelsMatrix{panel}(2)); - DATA.CursorXOfs = (c-1)*SET(NO).YSize; - DATA.CursorYOfs = (r-1)*SET(NO).XSize; - else - DATA.CursorXOfs = 0; - DATA.CursorYOfs = 0; - end; - - DATA.CursorX = repmat(DATA.CursorXOfs+x,1,5); - DATA.CursorY = repmat(DATA.CursorYOfs+y,1,5); - DATA.CursorN = 5; - - set(DATA.Handles.cursor(panel),'linestyle','-'); - - %Set up buttonup & motion - set(DATA.imagefig,'WindowButtonUpFcn',... - sprintf('%s(''crop_Buttonup'')',mfilename)); - - set(DATA.Handles.cursor(panel),'visible','on',... - 'xdata',DATA.CursorX,'ydata',DATA.CursorY); - - set(DATA.imagefig,'WindowButtonMotionFcn',... - sprintf('%s(''crop_Motion'')',mfilename)) - - otherwise - return; -end; - -%------------------------ -function crop_Motion %#ok -%------------------------ -%Motion function to crop the image stack - -global DATA SET NO - -[x2,y2,slice] = segment('getclickedcoords'); - -x1 = DATA.CursorX(1)-DATA.CursorXOfs; -y1 = DATA.CursorY(1)-DATA.CursorYOfs; -% first line is for montage -% second line is for one-view. -if (slice==SET(NO).CurrentSlice) && ... - (x2>0.5) && (y2>0.5) && (x2 -%-------------------------- -%Buttonup function for cropping of image stacks. - -global DATA SET NO - -%Restore -set(DATA.imagefig,'WindowButtonMotionFcn',''); -set(DATA.imagefig,'WindowButtonUpFcn',sprintf('%s(''buttonup_Callback'')','segment'));%Restore - -x1 = DATA.CursorX(1)-DATA.CursorXOfs; -y1 = DATA.CursorY(1)-DATA.CursorYOfs; -x2 = DATA.CursorX(3)-DATA.CursorXOfs; -y2 = DATA.CursorY(2)-DATA.CursorYOfs; - -%Restore -DATA.CursorN = 0; - -if ~yesno('Apply crop?',[],DATA.GUI.Segment) - set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - return; -end; - -updatetool('select'); - -set(DATA.Handles.cursor(DATA.CurrentPanel),'visible','off'); - -ydown = round(min([y1 y2])); -yup = round(max([y1 y2])); -xleft = round(min([x1 x2])); -xright = round(max([x1 x2])); - -ydown = max(ydown,1); -yup = min(yup,SET(NO).XSize); -xleft = max(xleft,1); -xright = min(xright,SET(NO).YSize); - -%------------------------------ -%---- Here we go start cropping -%------------------------------ - -%--- Calculate cropping index -xind = ydown:yup; -yind = xleft:xright; - -nos = crophelper(NO,xind,yind); -cropupdate(nos); - -%----------------------- -function cropupdate(nos) -%----------------------- -%Update image after a crop - -global DATA - -segment('update_thumbnail',nos); - -%DATA.ViewIM{DATA.CurrentPanel} = []; -for panelloop = find(ismember(DATA.ViewPanels,nos)) - DATA.ViewIM{panelloop} = []; + viewfunctions('setviewtype','one'); end -for no = nos - drawfunctions('drawimageno',no); -end - -disableundo; %-------------------------------------- -function nos = crophelper(no0,xind,yind) +function nos = crophelper(no0,xind,yind) %#ok %-------------------------------------- %This function is the enginge in cropping + global SET DATA %Find image stacks to crop @@ -2707,15 +2630,17 @@ function cropupdate(nos) if SET(no).Rotated SET(no).RotationCenter = SET(no).RotationCenter-yind(1)-1; - end; + end %ImageOrientation(1:3) is y in Segment %y direction SET(no).ImagePosition = SET(no).ImagePosition+(yind(1)-1)*SET(no).ResolutionY*SET(no).ImageOrientation(1:3); - + SET(no).RotatedImagePosition = SET(no).RotatedImagePosition+(yind(1)-1)*SET(no).ResolutionY*SET(no).RotatedImageOrientation(1:3); + %x direction SET(no).ImagePosition = SET(no).ImagePosition+(xind(1)-1)*SET(no).ResolutionX*SET(no).ImageOrientation(4:6); + SET(no).RotatedImagePosition = SET(no).RotatedImagePosition+(xind(1)-1)*SET(no).ResolutionX*SET(no).RotatedImageOrientation(4:6); %Remove from image SET(no).IM = SET(no).IM(xind,yind,:,:); @@ -2735,18 +2660,18 @@ function cropupdate(nos) DATA.EndoEDGE1 = DATA.EndoEDGE1(xind,yind,:,:); DATA.EndoEDGE2 = DATA.EndoEDGE2(xind,yind,:,:); DATA.EndoEDGE3 = DATA.EndoEDGE3(xind,yind,:,:); - end; + end if not(isempty(DATA.BALLOON)) && isequal(oldxsize,size(DATA.BALLOON,1)) && isequal(oldysize,size(DATA.BALLOON,2)) DATA.BALLOON = DATA.BALLOON(xind,yind,:,:); - end; + end if (DATA.EpiEdgeDetected) && isequal(oldxsize,size(DATA.EpiEDGE0,1)) && isequal(oldysize,size(DATA.EpiEDGE0,2)) DATA.EpiEDGE0 = DATA.EpiEDGE0(xind,yind,:,:); DATA.EpiEDGE1 = DATA.EpiEDGE1(xind,yind,:,:); DATA.EpiEDGE2 = DATA.EpiEDGE2(xind,yind,:,:); DATA.EpiEDGE3 = DATA.EpiEDGE3(xind,yind,:,:); - end; + end if ~isempty(SET(no).Scar) SET(no).Scar.IM = SET(no).Scar.IM(xind,yind,:); @@ -2759,16 +2684,16 @@ function cropupdate(nos) if ~isempty(SET(no).Scar.GreyZone) if ~isempty(SET(no).Scar.GreyZone.map) SET(no).Scar.GreyZone.map = SET(no).Scar.GreyZone.map(xind,yind,:,:,:); - end; - end; - end; + end + end + end if ~isempty(SET(no).MaR) SET(no).MaR.Auto = SET(no).MaR.Auto(xind,yind,:,:); SET(no).MaR.Result = SET(no).MaR.Result(xind,yind,:,:); SET(no).MaR.Manual = SET(no).MaR.Manual(xind,yind,:,:); SET(no).MaR.MyocardMask = SET(no).MaR.MyocardMask(xind,yind,:,:); - end; + end %Translate segmentation xofs = -xind(1)+1; @@ -2826,7 +2751,7 @@ function cropupdate(nos) warn=true; [SET(no).EpiX,SET(no).EpiY]=cropcontour(SET(no).EpiX,SET(no).EpiY); end - end; + end if ~isempty(SET(no).RVEndoX) SET(no).RVEndoX = SET(no).RVEndoX+xofs; @@ -2837,83 +2762,22 @@ function cropupdate(nos) warn=true; [SET(no).RVEndoX,SET(no).RVEndoY]=cropcontour(SET(no).RVEndoX,SET(no).RVEndoY); end - end; + end if ~isempty(SET(no).RVEpiX) SET(no).RVEpiX = SET(no).RVEpiX+xofs; SET(no).RVEpiY = SET(no).RVEpiY+yofs; tblr= (SET(no).RVEpiX<0.5) | (SET(no).RVEpiX>(SET(no0).XSize+0.5)) ... | (SET(no).RVEpiY<0.5) | (SET(no).RVEpiY>(SET(no0).YSize+0.5)); - if any(tblr(:)); + if any(tblr(:)) warn=true; [SET(no).RVEpiX,SET(no).RVEpiY]=cropcontour(SET(no).RVEpiX+xofs,SET(no).RVEpiY+yofs); end - end; + end % Interpolation points are lost, no big deal. segmentation('removeallinterp_Callback',true,no); -% pins - if ~isempty(SET(no).EndoPinX) - for zloop=1:SET(no).ZSize - for tloop=1:SET(no).TSize - SET(no).EndoPinX{tloop,zloop} = SET(no).EndoPinX{tloop,zloop}+xofs; - SET(no).EndoPinY{tloop,zloop} = SET(no).EndoPinY{tloop,zloop}+yofs; - ind= (SET(no).EndoPinX{tloop,zloop}>0.5)... - &(SET(no).EndoPinY{tloop,zloop}>0.5)... - &(SET(no).EndoPinX{tloop,zloop}0.5)... - &(SET(no).EpiPinY{tloop,zloop}>0.5)... - &(SET(no).EpiPinX{tloop,zloop}0.5)... - &(SET(no).RVEndoPinY{tloop,zloop}>0.5)... - &(SET(no).RVEndoPinX{tloop,zloop}0.5)... - &(SET(no).RVEpiPinY{tloop,zloop}>0.5)... - &(SET(no).RVEpiPinX{tloop,zloop}3 - temp=segment3dp.tools('levelsetunpack',obj,no); - temp=temp(xind,yind,:,:); + temp = segment3dp.tools('levelsetunpack',obj,no); + temp = temp(xind,yind,:,:); [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; else - temp=segment3dp.tools('levelsetunpack',obj,no); - temp=temp(xind,yind,:); + temp = segment3dp.tools('levelsetunpack',obj,no); + temp = temp(xind,yind,:); [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); - end; + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; + end end %crop .BW - SET(no).LevelSet.BW=SET(no0).LevelSet.BW(xind,yind,:,:); %Should still work with new gobject code - - %crop .Man - SET(no).LevelSet.Man=SET(no0).LevelSet.Man(xind,yind,:,:); - - %---things to change - - %Zoomstate - SET(no).LevelSet.View.RZoomState=[]; - SET(no).LevelSet.View.GZoomState=[]; - SET(no).LevelSet.View.BZoomState=[]; - - %slice - SET(no).LevelSet.View.GSlice=max(1,min(round(SET(no).LevelSet.View.GSlice+yofs),SET(no).YSize)); - SET(no).LevelSet.View.BSlice=max(1,min(round(SET(no).LevelSet.View.BSlice+xofs),SET(no).XSize)); - - %clear DATA.LevelSet - segment('cleardatalevelset'); + SET(no).LevelSet.BW = SET(no0).LevelSet.BW(xind,yind,:,:); %Should still work with new gobject code + + %crop .Man + DATA.LevelSet.Man = DATA.LevelSet.Man(xind,yind,:,:); + + %---things to change + + %Zoomstate + SET(no).LevelSet.View.RZoomState=[]; + SET(no).LevelSet.View.GZoomState=[]; + SET(no).LevelSet.View.BZoomState=[]; + + %slice + SET(no).LevelSet.View.GSlice=max(1,min(round(SET(no).LevelSet.View.GSlice+yofs),SET(no).YSize)); + SET(no).LevelSet.View.BSlice=max(1,min(round(SET(no).LevelSet.View.BSlice+xofs),SET(no).XSize)); + + segment3dp.tools('bwupdated'); + %clear DATA.LevelSet + %cleardatalevelset end %remove Strain tagging analysis @@ -2979,7 +2848,7 @@ function cropupdate(nos) SET(no).StrainTagging = []; end -end; %loop over image stacks +end %loop over image stacks %--- Some things that are only done for Mag in flow case. no=nos(1); @@ -3040,10 +2909,11 @@ function cropupdate(nos) if isfield(SET(no),'maxValue') SET(no).maxValue = single(max(SET(no).IM(:))); SET(no).minValue = single(min(SET(no).IM(:))); - end; + end if (warn) - mywarning('Cropping contours, may not work very well.',DATA.GUI.Segment); + mywarning('Cropping contours.',DATA.GUI.Segment); + segment('updatevolume'); end %---------------------------------------------------------- @@ -3154,7 +3024,7 @@ function cropupdate(nos) d = (ceil(f)-1)/2; else d = 0; -end; +end if isa(x,'double') x = x*f-d; @@ -3162,9 +3032,16 @@ function cropupdate(nos) for xloop=1:size(x,1) for yloop=1:size(x,2) x{xloop,yloop} = x{xloop,yloop}*f-d; - end; - end; -end; + end + end +end + +%------------------------------ +function makeisotropic_Callback %#ok +%------------------------------ +%Make an image stack isotropic + +makeisotropic; %call the root file, not very elegant, this function should be removed. %-------------------------------------- function newvol = upsampleinplane(f,vol,silent) @@ -3176,47 +3053,34 @@ function cropupdate(nos) end %Find new size -newsize = size(imresize(vol(:,:,1,1),f,'nearest')); +newsize = size(imresize(vol(:,:,1,1),f,'bicubic')); %Reserve memory -if isa(vol,'single') - newvol = repmat(single(0),[... - newsize(1) ... - newsize(2) ... - size(vol,3) ... - size(vol,4)]); -elseif isa(vol,'int16') - newvol = repmat(int16(0),[... - newsize(1) ... - newsize(2) ... - size(vol,3) ... - size(vol,4)]); -else - newvol = zeros(newsize(1),newsize(2),size(vol,3),size(vol,4)); -end; - +newvol = repmat(0*vol(1),[... + newsize(1) ... + newsize(2) ... + size(vol,3) ... + size(vol,4)]); + %Loop over image volume myworkon; if size(vol,3)>1 && ~silent h = mywaitbarstart(size(vol,3),'Please wait.'); -end; +end + for tloop=1:size(vol,3) - for zloop=1:size(vol,4) - if isa(vol,'single') - newvol(:,:,tloop,zloop) = single(imresize(vol(:,:,tloop,zloop),f,'bicubic')); - elseif isa(vol,'int16') - newvol(:,:,tloop,zloop) = int16(imresize(vol(:,:,tloop,zloop),f,'bicubic')); - else - newvol(:,:,tloop,zloop) = imresize(vol(:,:,tloop,zloop),f,'bicubic'); - end; - end; + for zloop=1:size(vol,4) + newvol(:,:,tloop,zloop) = single(imresize(vol(:,:,tloop,zloop),f,'bicubic')); + end if size(vol,3)>1 && ~silent h = mywaitbarupdate(h); - end; -end; + end +end + if size(vol,3)>1 && ~silent mywaitbarclose(h); -end; +end + myworkoff; %-------------------------------------- @@ -3224,7 +3088,9 @@ function cropupdate(nos) %-------------------------------------- %Helper function to upsample a volume vol. in this code f is a vector with %input [inplane x scalefactor, inplane y scale factor, temporal scale factor, slice scale factor] -global DATA +%global DATA + +%This function is not recommended. Instead use upsampleinplane if nargin < 3 silent = 0; @@ -3235,47 +3101,55 @@ function cropupdate(nos) f = f(1:length(oldsize)); %safety check for example if there is no slice dimension newsize = round(size(vol).*f); - oldtypefunc = str2func(class(vol)); - h = mywaitbarstart(2,'Please wait.'); +oldtypefunc = str2func(class(vol)); - if ~silent - h = mywaitbarupdate(h); - end; +if ~silent + h = mywaitbarstart(3,'Please wait.'); + h = mywaitbarupdate(h); +end - vectors=cell(1,length(oldsize)); - - for i=1:length(vectors) - vectors{i} = linspace(1,oldsize(i),newsize(i)); - end - grid=cell(1,sum(oldsize~=1)); - [grid{:}] = ndgrid(vectors{oldsize~=1}); - - if ~silent - h = mywaitbarupdate(h); - end; - - if DATA.Pref.GPU.Use - try - newvol = interpn(gpuArray(squeeze(vol)),grid{:},'linear'); - - newvol=gather(newvol); - catch - %newvol = interpn(single(squeeze(vol)),grid{:},'nearest'); - %newvol = interpn(single(squeeze(vol)),grid{:},'linear'); - - newvol = interpn(gpuArray(single(squeeze(vol))),grid{:},'linear'); - newvol=gather(newvol); - end - else - newvol = interpn(single(squeeze(vol)),grid{:},'linear'); +vectors = cell(1,length(oldsize)); + +for i=1:length(vectors) + vectors{i} = linspace(1,oldsize(i),newsize(i)); +end +grid = cell(1,sum(oldsize~=1)); +[grid{:}] = ndgrid(vectors{oldsize~=1}); + +if ~silent + h = mywaitbarupdate(h); +end + +%GPU does not work nicely +if false %DATA.Pref.GPU.Use + try + newvol = interpn(gpuArray(squeeze(vol)),grid{:},'linear'); + + newvol = gather(newvol); + catch + %newvol = interpn(single(squeeze(vol)),grid{:},'nearest'); + %newvol = interpn(single(squeeze(vol)),grid{:},'linear'); + resetgpu; + + %resort to CPU + disp('Resorting to CPU.'); + newvol = interpn(single(squeeze(vol)),grid{:},'linear'); + + %newvol = interpn(gpuArray(single(squeeze(vol))),grid{:},'linear'); + %newvol = gather(newvol); end - - - newvol = oldtypefunc(reshape(newvol,newsize)); - +else + newvol = interpn(single(squeeze(vol)),grid{:},'linear'); +end +if ~silent + h = mywaitbarupdate(h); +end + +newvol = oldtypefunc(reshape(newvol,newsize)); + if ~silent mywaitbarclose(h); -end; +end myworkoff; %-------------------------------------- @@ -3289,7 +3163,7 @@ function cropupdate(nos) if nargin < 3 silent = 0; end -warnstate = warning('off'); %#ok +warnstate = warning('off'); %Find new size switch ndims(vol) @@ -3301,7 +3175,7 @@ function cropupdate(nos) temp = squeeze(vol(1,:)); case 1 temp = vol; -end; +end xi = linspace(1,length(temp),round(length(temp)*f)); newsize = length(interp1(temp,xi,'nearest')); @@ -3309,7 +3183,7 @@ function cropupdate(nos) if newsize<1 myfailed('Too few resulting slices. Aborting.',DATA.GUI.Segment); return; -end; +end %Reserve memory zeroel = 0; @@ -3326,7 +3200,7 @@ function cropupdate(nos) % zeroel = int8(0); %case 'logical' % zeroel = false; -end; +end switch ndims(vol) case 4 @@ -3348,8 +3222,8 @@ function cropupdate(nos) if ~silent h = mywaitbarupdate(h); end - end; - end; + end + end if ~silent mywaitbarclose(h); end @@ -3371,7 +3245,7 @@ function cropupdate(nos) if ~silent h = mywaitbarupdate(h); end - end; + end if ~silent mywaitbarclose(h); end @@ -3382,7 +3256,7 @@ function cropupdate(nos) case 1 %z newvol = interp1(vol(:),xi,'linear'); -end; +end warning(warnstate) @@ -3412,18 +3286,18 @@ function cropupdate(nos) temp = SET(NO).IM(:,:,tloop,zloop); m(tloop)=mean(temp(:)); s(tloop)=std(temp(:)); - end; + end mm = mean(m); ss = mean(s); for tloop=1:SET(NO).TSize if not(ss==0) SET(NO).IM(:,:,tloop,zloop)=(SET(NO).IM(:,:,tloop,zloop)-m(tloop))*(ss/s(tloop))+mm; - end; - end; + end + end h = mywaitbarupdate(h); - end; + end mywaitbarclose(h); -end; +end %----------------------------- function mirrorx_Callback %#ok @@ -3431,10 +3305,10 @@ function cropupdate(nos) %Mirros in x direction. %Need to flip both x and z to maintain a righthand system. flipx_helper; -segment('updatemodeldisplay'); segment('updatevolume'); -segment('viewrefresh_Callback'); -drawfunctions('drawintersections'); + +%full refresh needed +viewfunctions('setview') %---------------------------------- function invertcolors_Callback %#ok @@ -3451,8 +3325,8 @@ function cropupdate(nos) end SET(NO).IM = 1-SET(NO).IM; -segment('makeviewim',DATA.CurrentPanel,NO); -drawfunctions('drawimageno'); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimage',DATA.CurrentPanel); %Find overall max tempmin = min(SET(NO).IM(:)); @@ -3468,10 +3342,10 @@ function cropupdate(nos) else SET(NO).IntensityScaling = 0; SET(NO).IntensityOffset = tempmin; - end; + end else SET(NO).IntensityScaling = 1; -end; +end %------------------------------- function normalize_Callback(no) %#ok @@ -3490,20 +3364,20 @@ function normalize_Callback(no) %#ok if ~isempty(SET(no).Flow.PhaseNo)&&(no==SET(no).Flow.PhaseNo) myfailed('You can not normalize phase image',DATA.GUI.Segment); return; - end; + end if ~isempty(SET(no).Flow.PhaseX)&&(no==SET(no).Flow.PhaseX) myfailed('You can not normalize phase image',DATA.GUI.Segment); return; - end; + end if ~isempty(SET(no).Flow.PhaseY)&&(no==SET(no).Flow.PhaseY) myfailed('You can not normalize phase image',DATA.GUI.Segment); return; - end; + end elseif isfield(SET(no),'Linked') && ~isempty(SET(no).Linked) %Normalize all linked stacks - mydisp('Normalizing data'); + disp('Normalizing data'); for linked_no = SET(no).Linked - if isa(SET(linked_no).IM,'single'), + if isa(SET(linked_no).IM,'single') [tempmin,tempmax] = mynormalize(SET(linked_no).IM); SET(linked_no).IntensityScaling = tempmax-tempmin; @@ -3517,15 +3391,15 @@ function normalize_Callback(no) %#ok DATA.EndoEdgeDetected = false; DATA.EpiEdgeDetected = false; return -end; +end %Normalize %only if bigger than one. -mydisp('Normalizing data'); +disp('Normalizing data'); % This fcn makes changes to SET(NO).IM directly % Very uggly but saves a lot of memory for large datasets. -if isa(SET(no).IM,'single'), +if isa(SET(no).IM,'single') [tempmin,tempmax] = mynormalize(SET(no).IM); SET(no).IntensityScaling = tempmax-tempmin; @@ -3553,8 +3427,8 @@ function undosegmentation_Callback(no) %#ok no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; - end; -end; + end +end if strcmp(DATA.CurrentTheme,'3dp') segment3dp.tools('undo_Callback') @@ -3565,15 +3439,13 @@ function undosegmentation_Callback(no) %#ok mywarning('Nothing to undo.',DATA.GUI.Segment); disableundo; return; -end; +end if (DATA.UndoN(no)<1) mywarning('Nothing to undo.',DATA.GUI.Segment); disableundo; return; -end; - -set(DATA.Handles.undosegmentationicon,'enable','on','state','off'); +end SET(no).EndoX = DATA.Undo(no,DATA.UndoN(no)).EndoXBackup; SET(no).EndoY = DATA.Undo(no,DATA.UndoN(no)).EndoYBackup; @@ -3583,14 +3455,6 @@ function undosegmentation_Callback(no) %#ok SET(no).RVEndoY = DATA.Undo(no,DATA.UndoN(no)).RVEndoYBackup; SET(no).RVEpiX = DATA.Undo(no,DATA.UndoN(no)).RVEpiXBackup; SET(no).RVEpiY = DATA.Undo(no,DATA.UndoN(no)).RVEpiYBackup; -SET(no).EndoPinX = DATA.Undo(no,DATA.UndoN(no)).EndoPinXBackup; -SET(no).EndoPinY = DATA.Undo(no,DATA.UndoN(no)).EndoPinYBackup; -SET(no).EpiPinX = DATA.Undo(no,DATA.UndoN(no)).EpiPinXBackup; -SET(no).EpiPinY = DATA.Undo(no,DATA.UndoN(no)).EpiPinYBackup; -SET(no).RVEndoPinX = DATA.Undo(no,DATA.UndoN(no)).RVEndoPinXBackup; -SET(no).RVEndoPinY = DATA.Undo(no,DATA.UndoN(no)).RVEndoPinYBackup; -SET(no).RVEpiPinX = DATA.Undo(no,DATA.UndoN(no)).RVEpiPinXBackup; -SET(no).RVEpiPinY = DATA.Undo(no,DATA.UndoN(no)).RVEpiPinYBackup; SET(no).EndoInterpX = DATA.Undo(no,DATA.UndoN(no)).EndoInterpXBackup; SET(no).EndoInterpY = DATA.Undo(no,DATA.UndoN(no)).EndoInterpYBackup; SET(no).EpiInterpX = DATA.Undo(no,DATA.UndoN(no)).EpiInterpXBackup; @@ -3657,12 +3521,14 @@ function undosegmentation_Callback(no) %#ok if DATA.UndoN(no)<1 DATA.UndoN(no) = 0; disableundo; -end; +end -segment('updatemodeldisplay'); segment('updatevolume'); -drawfunctions('drawimageno'); -drawfunctions('drawallslices'); +drawfunctions('drawno',no,true) +% for p = find(DATA.ViewPanels) +% DATA.ViewIM{p} = []; +% drawfunctions('drawno',p,true) +% end %------------------------------------------ @@ -3675,88 +3541,142 @@ function smoothsegmentation_Callback(no) %#ok no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; - end; -end; + end +end + %smooth segmentation in current slice and current time frame -if isequal(DATA.CurrentTool,'drawendo') || isequal(DATA.CurrentTool,'interpendo') - %smooth LV endo - if not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) - endox = SET(no).EndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - endoy = SET(no).EndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - sigma = 1; - %re-parameterize to radial components - centerx = mean(endox); - centery = mean(endoy); - dist2center = sqrt((endox-centerx).^2+(endoy-centery).^2); - tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); - tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); - smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); - %re-paramterize to x-y-components again - tempangle = asin((endoy-centery)./dist2center); - angle = zeros(length(endox),1); - for angleloop = 1:length(endoy) - if (endoy(angleloop)-centery) > 0 && (endox(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop); - elseif (endoy(angleloop)-centery) < 0 && (endox(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop)+2*pi; - elseif (endoy(angleloop)-centery) < 0 && (endox(angleloop)-centerx) > 0 - angle(angleloop) = pi-tempangle(angleloop); - else - angle(angleloop) = pi-tempangle(angleloop); +switch DATA.CurrentTool + case {'Endo','EndoInterp','EndoBalloon'} + %Double check so that there is a cell with the correct size for the used + %type + %delete interpolation points if they exist + tools('connectinterpolation',no,{'EndoInterp'}) + if ~isempty(SET(no).EndoInterpX) + if ~all([size(SET(no).EndoInterpX,1)==SET(no).TSize,size(SET(no).EndoInterpX,2)==SET(no).ZSize]) + tmpX = cell(SET(no).TSize,SET(no).ZSize); + tmpY = cell(SET(no).TSize,SET(no).ZSize); + sz = size(SET(no).EndoInterpX); + tmpX(1:sz(1),1:sz(2)) = SET(no).EndoInterpX(1:sz(1),1:sz(2)); + tmpY(1:sz(1),1:sz(2)) = SET(no).EndoInterpX(1:sz(1),1:sz(2)); + SET(no).EndoInterpX = tmpX; + SET(no).EndoInterpY = tmpY; + end + SET(no).EndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + SET(no).EndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + end + + % callbackfunctions('interpdeletepointall','EndoInterp'); + %smooth LV endo + if not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) + endox = SET(no).EndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + endoy = SET(no).EndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + sigma = 1; + %re-parameterize to radial components + centerx = mean(endox); + centery = mean(endoy); + dist2center = sqrt((endox-centerx).^2+(endoy-centery).^2); + tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); + tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); + smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); + %re-paramterize to x-y-components again + tempangle = asin((endoy-centery)./dist2center); + angle = zeros(length(endox),1); + for angleloop = 1:length(endoy) + if (endoy(angleloop)-centery) > 0 && (endox(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop); + elseif (endoy(angleloop)-centery) < 0 && (endox(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop)+2*pi; + elseif (endoy(angleloop)-centery) < 0 && (endox(angleloop)-centerx) > 0 + angle(angleloop) = pi-tempangle(angleloop); + else + angle(angleloop) = pi-tempangle(angleloop); + end end + SET(no).EndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); + SET(no).EndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); + SET(no).EndoX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + SET(no).EndoY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EndoY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + else + mywarning('No LV endo segmentation to smooth.',DATA.GUI.Segment); + return; end - SET(no).EndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); - SET(no).EndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); - SET(no).EndoX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EndoY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EndoY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - SET(no).EndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - else - mywarning('No LV endo segmentation to smooth.',DATA.GUI.Segment); - return; - end -elseif isequal(DATA.CurrentTool,'drawepi') || isequal(DATA.CurrentTool,'interpepi') - %smooth LV epi - if not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) - epix = SET(no).EpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - epiy = SET(no).EpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - sigma = 1; - %re-parameterize to radial components - centerx = mean(epix); - centery = mean(epiy); - dist2center = sqrt((epix-centerx).^2+(epiy-centery).^2); - tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); - tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); - smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); - %re-paramterize to x-y-components again - tempangle = asin((epiy-centery)./dist2center); - angle = zeros(length(epix),1); - for angleloop = 1:length(epiy) - if (epiy(angleloop)-centery) > 0 && (epix(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop); - elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop)+2*pi; - elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) > 0 - angle(angleloop) = pi-tempangle(angleloop); - else - angle(angleloop) = pi-tempangle(angleloop); + case {'Epi','EpiInterp','EpiBalloon'} + %Double check so that there is a cell with the correct size for the used + %type + tools('connectinterpolation',no,{'EpiInterp'}) + %delete interpolation points if they exist + if ~isempty(SET(no).EpiInterpX) + if ~all([size(SET(no).EpiInterpX,1)==SET(no).TSize,size(SET(no).EpiInterpX,2)==SET(no).ZSize]) + tmpX = cell(SET(no).TSize,SET(no).ZSize); + tmpY = cell(SET(no).TSize,SET(no).ZSize); + sz = size(SET(no).EpiInterpX); + tmpX(1:sz(1),1:sz(2)) = SET(no).EpiInterpX(1:sz(1),1:sz(2)); + tmpY(1:sz(1),1:sz(2)) = SET(no).EpiInterpX(1:sz(1),1:sz(2)); + SET(no).EpiInterpX = tmpX; + SET(no).EpiInterpY = tmpY; + end + + SET(no).EpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + SET(no).EpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + end + + % callbackfunctions('interpdeletepointall','EpiInterp'); + %smooth LV epi + if not(isnan(SET(no).EpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) + epix = SET(no).EpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + epiy = SET(no).EpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + sigma = 1; + %re-parameterize to radial components + centerx = mean(epix); + centery = mean(epiy); + dist2center = sqrt((epix-centerx).^2+(epiy-centery).^2); + tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); + tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); + smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); + %re-paramterize to x-y-components again + tempangle = asin((epiy-centery)./dist2center); + angle = zeros(length(epix),1); + for angleloop = 1:length(epiy) + if (epiy(angleloop)-centery) > 0 && (epix(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop); + elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop)+2*pi; + elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) > 0 + angle(angleloop) = pi-tempangle(angleloop); + else + angle(angleloop) = pi-tempangle(angleloop); + end end + SET(no).EpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); + SET(no).EpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); + SET(no).EpiX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + SET(no).EpiY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EpiY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + else + mywarning('No LV epi segmentation to smooth.',DATA.GUI.Segment); + return; end - SET(no).EpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); - SET(no).EpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); - SET(no).EpiX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EpiY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).EpiY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).EpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - SET(no).EpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - else - mywarning('No LV epi segmentation to smooth.',DATA.GUI.Segment); - return; + case {'RVEndo','RVEndoInterp','RVEndoBalloon'} + %Double check so that there is a cell with the correct size for the used + %type + %delete interpolation points if they exist + tools('connectinterpolation',no,{'RVEndoInterp'}) + if ~isempty(SET(no).RVEndoInterpX) + if ~all([size(SET(no).RVEndoInterpX,1)==SET(no).TSize,size(SET(no).RVEndoInterpX,2)==SET(no).ZSize]) + tmpX = cell(SET(no).TSize,SET(no).ZSize); + tmpY = cell(SET(no).TSize,SET(no).ZSize); + sz = size(SET(no).RVEndoInterpX); + tmpX(1:sz(1),1:sz(2)) = SET(no).RVEndoInterpX(1:sz(1),1:sz(2)); + tmpY(1:sz(1),1:sz(2)) = SET(no).RVEndoInterpX(1:sz(1),1:sz(2)); + SET(no).RVEndoInterpX = tmpX; + SET(no).RVEndoInterpY = tmpY; + end + SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; end -elseif isequal(DATA.CurrentTool,'drawrvendo') || isequal(DATA.CurrentTool,'interprvendo') %smooth RV endo - if not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) + if not(isnan(SET(no).RVEndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) endox = SET(no).RVEndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); endoy = SET(no).RVEndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); sigma = 1; @@ -3781,98 +3701,122 @@ function smoothsegmentation_Callback(no) %#ok angle(angleloop) = pi-tempangle(angleloop); end end - SET(no).RVEndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); - SET(no).RVEndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); + x = centerx+smoothedline.*sin(angle-pi/2); + y = centery+smoothedline.*cos(angle-pi/2); + [x,y] = calcfunctions('calcpointsoutsideLV',x,y,no); + SET(no).RVEndoX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = x; + SET(no).RVEndoY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = y; SET(no).RVEndoX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).RVEndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); SET(no).RVEndoY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).RVEndoY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEndoInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - SET(no).RVEndoInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; else mywarning('No RV endo segmentation to smooth.',DATA.GUI.Segment); return; end -elseif isequal(DATA.CurrentTool,'drawrvepi') || isequal(DATA.CurrentTool,'interprvepi') + case {'RVEpi','RVEpiInterp'} + %Double check so that there is a cell with the correct size for the used + %type + %delete interpolation points if they exist + tools('connectinterpolation',no,{'RVEpiInterp'}) + if ~isempty(SET(no).RVEpiInterpX) + if ~all([size(SET(no).RVEpiInterpX,1)==SET(no).TSize,size(SET(no).RVEpiInterpX,2)==SET(no).ZSize]) + tmpX = cell(SET(no).TSize,SET(no).ZSize); + tmpY = cell(SET(no).TSize,SET(no).ZSize); + sz = size(SET(no).RVEpiInterpX); + tmpX(1:sz(1),1:sz(2)) = SET(no).RVEpiInterpX(1:sz(1),1:sz(2)); + tmpY(1:sz(1),1:sz(2)) = SET(no).RVEpiInterpX(1:sz(1),1:sz(2)); + SET(no).RVEpiInterpX = tmpX; + SET(no).RVEpiInterpY = tmpY; + end + SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + end %smooth RV epi - if not(isnan(SET(no).EndoX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) - epix = SET(no).RVEpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - epiy = SET(no).RVEpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - sigma = 1; - %re-parameterize to radial components - centerx = mean(epix); - centery = mean(epiy); - dist2center = sqrt((epix-centerx).^2+(epiy-centery).^2); - tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); - tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); - smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); - %re-paramterize to x-y-components again - tempangle = asin((epiy-centery)./dist2center); - angle = zeros(length(epix),1); - for angleloop = 1:length(epiy) - if (epiy(angleloop)-centery) > 0 && (epix(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop); - elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop)+2*pi; - elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) > 0 - angle(angleloop) = pi-tempangle(angleloop); - else - angle(angleloop) = pi-tempangle(angleloop); + if not(isnan(SET(no).RVEpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice))) + epix = SET(no).RVEpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + epiy = SET(no).RVEpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + sigma = 1; + %re-parameterize to radial components + centerx = mean(epix); + centery = mean(epiy); + dist2center = sqrt((epix-centerx).^2+(epiy-centery).^2); + tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); + tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); + smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); + %re-paramterize to x-y-components again + tempangle = asin((epiy-centery)./dist2center); + angle = zeros(length(epix),1); + for angleloop = 1:length(epiy) + if (epiy(angleloop)-centery) > 0 && (epix(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop); + elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop)+2*pi; + elseif (epiy(angleloop)-centery) < 0 && (epix(angleloop)-centerx) > 0 + angle(angleloop) = pi-tempangle(angleloop); + else + angle(angleloop) = pi-tempangle(angleloop); + end end + SET(no).RVEpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); + SET(no).RVEpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); + SET(no).RVEpiX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).RVEpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + SET(no).RVEpiY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).RVEpiY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); + else + mywarning('No RV epi segmentation to smooth.',DATA.GUI.Segment); + return; end - SET(no).RVEpiX(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centerx+smoothedline.*sin(angle-pi/2); - SET(no).RVEpiY(1:end-1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = centery+smoothedline.*cos(angle-pi/2); - SET(no).RVEpiX(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).RVEpiX(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEpiY(end,SET(no).CurrentTimeFrame,SET(no).CurrentSlice) = SET(no).RVEpiY(1,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - SET(no).RVEpiInterpX{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - SET(no).RVEpiInterpY{SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; - else - mywarning('No RV epi segmentation to smooth.',DATA.GUI.Segment); - return; - end -elseif isequal(DATA.CurrentTool,'drawroi') || isequal(DATA.CurrentTool,'putroi') - %smooth ROI - if not(isempty(SET(no).RoiCurrent)) - x = SET(no).Roi(SET(no).RoiCurrent).X(1:end-1,SET(no).CurrentTimeFrame); - y = SET(no).Roi(SET(no).RoiCurrent).Y(1:end-1,SET(no).CurrentTimeFrame); - sigma = 1; - %re-parameterize to radial components - centerx = mean(x); - centery = mean(y); - dist2center = sqrt((x-centerx).^2+(y-centery).^2); - tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); - tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); - smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); - %re-paramterize to x-y-components again - tempangle = asin((y-centery)./dist2center); - angle = zeros(length(x),1); - for angleloop = 1:length(y) - if (y(angleloop)-centery) > 0 && (x(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop); - elseif (y(angleloop)-centery) < 0 && (x(angleloop)-centerx) < 0 - angle(angleloop) = tempangle(angleloop)+2*pi; - elseif (y(angleloop)-centery) < 0 && (x(angleloop)-centerx) > 0 - angle(angleloop) = pi-tempangle(angleloop); - else - angle(angleloop) = pi-tempangle(angleloop); + case {'Roi','drawroi','putroi','RoiBalloon'} + %smooth ROI + if not(isempty(SET(no).RoiCurrent)) + x = SET(no).Roi(SET(no).RoiCurrent).X(1:end-1,SET(no).CurrentTimeFrame); + y = SET(no).Roi(SET(no).RoiCurrent).Y(1:end-1,SET(no).CurrentTimeFrame); + sigma = 1; + %re-parameterize to radial components + centerx = mean(x); + centery = mean(y); + dist2center = sqrt((x-centerx).^2+(y-centery).^2); + tempsmoothedline = lvpeter('smooth1D',[dist2center ; dist2center ; dist2center],sigma); + tempsmoothedline = lvpeter('smooth1D',tempsmoothedline,sigma); + smoothedline = tempsmoothedline(length(dist2center)+1:2*length(dist2center)); + %re-paramterize to x-y-components again + tempangle = asin((y-centery)./dist2center); + angle = zeros(length(x),1); + for angleloop = 1:length(y) + if (y(angleloop)-centery) > 0 && (x(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop); + elseif (y(angleloop)-centery) < 0 && (x(angleloop)-centerx) < 0 + angle(angleloop) = tempangle(angleloop)+2*pi; + elseif (y(angleloop)-centery) < 0 && (x(angleloop)-centerx) > 0 + angle(angleloop) = pi-tempangle(angleloop); + else + angle(angleloop) = pi-tempangle(angleloop); + end end + roiXtemp = centerx+smoothedline.*sin(angle-pi/2); + roiYtemp = centery+smoothedline.*cos(angle-pi/2); + roiXtemp(end+1) = roiXtemp(1); + roiYtemp(end+1) = roiYtemp(1); + SET(no).Roi(SET(no).RoiCurrent).X(:,SET(no).CurrentTimeFrame) = roiXtemp; + SET(no).Roi(SET(no).RoiCurrent).Y(:,SET(no).CurrentTimeFrame) = roiYtemp; + else + mywarning('No ROI segmentation to smooth.',DATA.GUI.Segment); + return; end - roiXtemp = centerx+smoothedline.*sin(angle-pi/2); - roiYtemp = centery+smoothedline.*cos(angle-pi/2); - roiXtemp(end+1) = roiXtemp(1); - roiYtemp(end+1) = roiYtemp(1); - SET(no).Roi(SET(no).RoiCurrent).X(:,SET(no).CurrentTimeFrame) = roiXtemp; - SET(no).Roi(SET(no).RoiCurrent).Y(:,SET(no).CurrentTimeFrame) = roiYtemp; - else - mywarning('No ROI segmentation to smooth.',DATA.GUI.Segment); - return; - end end -segment('updatemodeldisplay'); segment('updatevolume'); -drawfunctions('drawimageno'); -drawfunctions('drawallslices'); +drawfunctions('drawno',no) +%ensure strain calculation is re-done if lv segmentation is changed +if ~isempty(SET(no).StrainTagging) && isfield(SET(no).StrainTagging, 'LVupdated') + SET(no).StrainTagging.LVupdated = 1; +end +calcfunctions('updatemarandscar',no); +% %update rois and contours +% calcfunctions('segmentationintersection_helper',DATA.CurrentPanel,SET(no).CurrentTimeFrame) +% drawfunctions('drawplaneintersections') +% drawfunctions('drawcontours',DATA.CurrentPanel); +% drawfunctions('drawroi',DATA.CurrentPanel); %-------------------------------- function endsystole_Callback(noupdate,single) @@ -3880,6 +3824,12 @@ function endsystole_Callback(noupdate,single) %Change current time frame to end systole global DATA SET NO +if (DATA.Run) && (findindented(DATA.Handles.permanenticonholder,'play')) + % stop playing + DATA.Run = 0; + undent(DATA.Handles.permanenticonholder,'play',0) +end + if nargin==0 noupdate=false; end @@ -3898,6 +3848,13 @@ function endsystole_Callback(noupdate,single) include(i) = ismember(SET(nos(i)).ImageViewPlane,imvpcell)||ismember(SET(nos(i)).ImageType,imtcell); end +%if no image stack fulfilling the criteria above, still change for current +%image stack +if sum(include(:)) == 0 + [~,NOindex] = find(nos==NO); + include(NOindex) = 1; +end + nos=nos(logical(include)); if length(DATA.LVNO)==1 no = DATA.LVNO; @@ -3929,18 +3886,19 @@ function endsystole_Callback(noupdate,single) if single SET(NO).CurrentTimeFrame = SET(NO).EST; - drawfunctions('drawsliceno',NO); + drawfunctions('drawpanel',DATA.CurrentPanel); else for loop=1:length(nos) SET(nos(loop)).CurrentTimeFrame = SET(nos(loop)).EST; - end; - for loop=1:length(nos) - drawfunctions('drawsliceno',nos(loop)); + end + for p = find(ismember(DATA.ViewPanels,nos)) + drawfunctions('drawpanel',p); end end if ~noupdate segment('updatevolume'); end +viewfunctions('updatetimebars'); %--------------------------------- function enddiastole_Callback(noupdate,single) @@ -3949,6 +3907,13 @@ function enddiastole_Callback(noupdate,single) % global DATA SET NO +if (DATA.Run) && (findindented(DATA.Handles.permanenticonholder,'play')) + % stop playing + DATA.Run = 0; + undent(DATA.Handles.permanenticonholder,'play',0) +end + + if nargin==0 noupdate=false; end @@ -3967,6 +3932,13 @@ function enddiastole_Callback(noupdate,single) include(i) = ismember(SET(nos(i)).ImageViewPlane,imvpcell)||ismember(SET(nos(i)).ImageType,imtcell); end +%if no image stack fulfilling the criteria above, still change for current +%image stack +if sum(include(:)) == 0 + [~,NOindex] = find(nos==NO); + include(NOindex) = 1; +end + nos=nos(logical(include)); if length(DATA.LVNO)==1%~isempty(DATA.LVNO) no = DATA.LVNO; @@ -3999,18 +3971,19 @@ function enddiastole_Callback(noupdate,single) if single SET(NO).CurrentTimeFrame = SET(NO).EDT; - drawfunctions('drawsliceno',NO); + drawfunctions('drawpanel',DATA.CurrentPanel); else for loop=1:length(nos) SET(nos(loop)).CurrentTimeFrame = SET(nos(loop)).EDT; - end; - for loop=1:length(nos) - drawfunctions('drawsliceno',nos(loop)); + end + for p = find(ismember(DATA.ViewPanels,nos)) + drawfunctions('drawpanel',p); end end if ~noupdate segment('updatevolume'); end +viewfunctions('updatetimebars'); %-------------------------------- function endsystoleall_Callback %#ok @@ -4073,42 +4046,42 @@ function copyforwardselected_Callback(lv) %#ok tf = 1; else tf = SET(NO).CurrentTimeFrame+1; -end; +end if nargin > 0 && isequal(lv,'lv') - currenttool = 'drawendo'; + currenttool = 'Endo'; else currenttool = DATA.CurrentTool; end switch currenttool - case 'drawroi' + case {'Roi','RoiPut'} for n = SET(NO).RoiCurrent SET(NO).Roi(n).X(:,tf) = SET(NO).Roi(n).X(:,SET(NO).CurrentTimeFrame); SET(NO).Roi(n).Y(:,tf) = SET(NO).Roi(n).Y(:,SET(NO).CurrentTimeFrame); SET(NO).Roi(n).T = find(not(isnan(SET(NO).Roi(n).X(1,:)))); end - case {'drawendo','drawepi'} + case {'Endo','Epi'} ind = SET(NO).StartSlice:SET(NO).EndSlice; if isempty(ind) myfailed('No slices selected.',DATA.GUI.Segment); return; - end; + end if ~isempty(SET(NO).EndoX) SET(NO).EndoX(:,tf,ind) = SET(NO).EndoX(:,SET(NO).CurrentTimeFrame,ind); SET(NO).EndoY(:,tf,ind) = SET(NO).EndoY(:,SET(NO).CurrentTimeFrame,ind); - end; + end if ~isempty(SET(NO).EpiX) SET(NO).EpiX(:,tf,ind) = SET(NO).EpiX(:,SET(NO).CurrentTimeFrame,ind); SET(NO).EpiY(:,tf,ind) = SET(NO).EpiY(:,SET(NO).CurrentTimeFrame,ind); - end; -end; + end +end SET(NO).CurrentTimeFrame = SET(NO).CurrentTimeFrame+1; -segment('updatemodeldisplay'); -drawfunctions('drawimageno'); +drawfunctions('drawpanel',DATA.CurrentPanel); + %-------------------------------------------------- function copyupward_Callback(type,silent,dolv,lvalg) %#ok @@ -4123,15 +4096,15 @@ function copyupward_Callback(type,silent,dolv,lvalg) %#ok if nargin<2 silent = false; -end; +end if nargin<3 if isequal(DATA.CurrentTheme,'lv') dolv = true; else dolv = false; - end; -end; + end +end if nargin<4 lvalg = 'new'; @@ -4140,14 +4113,18 @@ function copyupward_Callback(type,silent,dolv,lvalg) %#ok if nargin<1 endo = 1; epi = 1; + rvendo = 1; + rvepi = 1; else endo = isequal(type,'endo'); epi = isequal(type,'epi'); + rvendo = isequal(type,'rvendo'); + rvepi = isequal(type,'rvepi'); if isequal(type,'lv') endo =1; epi = 1; end -end; +end % if strcmp(DATA.ProgramName,'Segment CMR') % DATA.ThisFrameOnly = false; @@ -4160,33 +4137,37 @@ function copyupward_Callback(type,silent,dolv,lvalg) %#ok timeframes = SET(NO).CurrentTimeFrame; else timeframes = 1:SET(NO).TSize; -end; +end %check if contour exist in selected all slices and timeframes docontinue=true; -if endo - if dolv %lvendo +if dolv + if endo %lvendo + tools('connectinterpolation',NO,{'EndoInterp'}) if not(existfunctions('existendoinselected',NO))%check so that lvendo exist in all slices and frames docontinue=false; errmsg='Endo must exist in all timeframes or '; end - else%rvendo - if not(existfunctions('existrvendoinselected',NO))%check so that rvendo exist in all slices and frames + else %lvepi + tools('connectinterpolation',NO,{'EpiInterp'}) + if not(existfunctions('existepiinselected',NO))%check so that lvepi exist in all slices and frames docontinue=false; - errmsg='RV Endo must exist in all timeframes or '; + errmsg='Epi must exist in all timeframes or '; end end -else %lvepi - if not(existfunctions('existepiinselected',NO))%check so that lvepi exist in all slices and frames +else%rvendo + tools('connectinterpolation',NO,{'RVEndoInterp'}) + if not(existfunctions('existrvendoinselected',NO))%check so that rvendo exist in all slices and frames docontinue=false; - errmsg='Epi must exist in all timeframes or '; + errmsg='RV Endo must exist in all timeframes or '; end end + %do not continue calculations if contour does not exist in all selectedtimeframes %ans slices if not(docontinue) tip = DATA.singleframetip; - myfailed(dprintf('%s%s',errmsg,tip)); + myfailed(sprintf('%s%s',errmsg,tip)); return; end @@ -4197,58 +4178,56 @@ function copyupward_Callback(type,silent,dolv,lvalg) %#ok if (endo)&&(~isempty(SET(NO).EndoX)) SET(NO).EndoX(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).EndoX(:,timeframes,SET(NO).CurrentSlice); SET(NO).EndoY(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).EndoY(:,timeframes,SET(NO).CurrentSlice); - end; + end else - if (endo)&&(~isempty(SET(NO).RVEndoX)) + if (rvendo)&&(~isempty(SET(NO).RVEndoX)) SET(NO).RVEndoX(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).RVEndoX(:,timeframes,SET(NO).CurrentSlice); SET(NO).RVEndoY(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).RVEndoY(:,timeframes,SET(NO).CurrentSlice); - end; - end; + end + end if dolv if (epi)&&(~isempty(SET(NO).EpiY)) SET(NO).EpiX(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).EpiX(:,timeframes,SET(NO).CurrentSlice); SET(NO).EpiY(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).EpiY(:,timeframes,SET(NO).CurrentSlice); - end; + end else - if (epi)&&(~isempty(SET(NO).RVEpiY)) + if (rvepi)&&(~isempty(SET(NO).RVEpiY)) SET(NO).RVEpiX(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).RVEpiX(:,timeframes,SET(NO).CurrentSlice); SET(NO).RVEpiY(:,timeframes,SET(NO).CurrentSlice-1) = SET(NO).RVEpiY(:,timeframes,SET(NO).CurrentSlice); - end; - end; + end + end SET(NO).CurrentSlice = SET(NO).CurrentSlice-1; SET(NO).StartSlice = SET(NO).CurrentSlice; SET(NO).EndSlice = SET(NO).StartSlice; - if endo - if dolv + if dolv + if endo switch lvalg case 'old' lv('segmentrefineendo_Callback',silent); case 'new' lvpeter('segmentrefineendo_Callback',silent); end - else - rv('segmentrefinervendo_Callback',silent,false); - end; - end; - if epi - if dolv - switch lvalg - case 'old' - lv('segmentrefineepi_Callback',silent); - case 'new' - lvpeter('segmentrefineepi_Callback',silent); - end - end; - end; + end + elseif rvendo + rv('segmentrefinervendo_Callback',silent,false); + end + if epi && dolv + switch lvalg + case 'old' + lv('segmentrefineepi_Callback',silent); + case 'new' + lvpeter('segmentrefineepi_Callback',silent); + end + end if not(silent) - SET(NO).CurrentSlice = SET(NO).CurrentSlice+1; %movetowardsbase undoes this. - segment('movetowardsbase_Callback'); %This really updates graphics correctly - end; -end; + DATA.ViewIM{DATA.CurrentPanel} = []; + drawfunctions('drawno',NO) + end +end %---------------------------------------------------- function copydownward_Callback(type,silent,dolv,lvalg) %#ok @@ -4258,7 +4237,7 @@ function copydownward_Callback(type,silent,dolv,lvalg) %#ok if nargin<2 silent = false; -end; +end if nargin<3 % Be extra sure @@ -4266,8 +4245,8 @@ function copydownward_Callback(type,silent,dolv,lvalg) %#ok dolv = true; else dolv = false; - end; -end; + end +end if nargin<4 lvalg = 'new'; @@ -4276,14 +4255,18 @@ function copydownward_Callback(type,silent,dolv,lvalg) %#ok if nargin<1 endo = 1; epi = 1; + rvendo = 1; + rvepi = 1; else endo = isequal(type,'endo'); epi = isequal(type,'epi'); + rvendo = isequal(type,'rvendo'); + rvepi = isequal(type,'rvepi'); if isequal(type,'lv') endo =1; epi = 1; end -end; +end %if strcmp(DATA.ProgramName,'Segment CMR') % for Segment CMR, do it for all time frames if endo exist in all, @@ -4297,23 +4280,27 @@ function copydownward_Callback(type,silent,dolv,lvalg) %#ok timeframes = SET(NO).CurrentTimeFrame; else timeframes = 1:SET(NO).TSize; -end; +end %check if contour exist in selected all slices and timeframes docontinue=true; -if endo - if dolv %lvendo +if dolv + tools('connectinterpolation',NO,{'EndoInterp'}) + if endo %lvendo if not(existfunctions('existendoinselected',NO))%check so that lvendo exist in all slices and frames docontinue=false; errmsg='Endo must exist in all timeframes or '; end - else%rvendo - if not(existfunctions('existrvendoinselected',NO))%check so that rvendo exist in all slices and frames - docontinue=false; - errmsg='RV Endo must exist in all timeframes or '; - end end -else %lvepi +else%rvendo + tools('connectinterpolation',NO,{'RVEndoInterp'}) + if not(existfunctions('existrvendoinselected',NO))%check so that rvendo exist in all slices and frames + docontinue=false; + errmsg='RV Endo must exist in all timeframes or '; + end +end +if dolv && epi %lvepi + tools('connectinterpolation',NO,{'EpiInterp'}) if not(existfunctions('existepiinselected',NO))%check so that lvepi exist in all slices and frames docontinue=false; errmsg='Epi must exist in all timeframes or '; @@ -4323,7 +4310,7 @@ function copydownward_Callback(type,silent,dolv,lvalg) %#ok %ans slices if not(docontinue) tip = DATA.singleframetip; - myfailed(dprintf('%s%s',errmsg,tip)); + myfailed(sprintf('%s%s',errmsg,tip)); return; end @@ -4334,56 +4321,54 @@ function copydownward_Callback(type,silent,dolv,lvalg) %#ok if (endo)&&(~isempty(SET(NO).EndoX)) SET(NO).EndoX(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).EndoX(:,timeframes,SET(NO).CurrentSlice); SET(NO).EndoY(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).EndoY(:,timeframes,SET(NO).CurrentSlice); - end; + end else - if (endo)&&(~isempty(SET(NO).RVEndoX)) + if (rvendo)&&(~isempty(SET(NO).RVEndoX)) SET(NO).RVEndoX(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).RVEndoX(:,timeframes,SET(NO).CurrentSlice); SET(NO).RVEndoY(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).RVEndoY(:,timeframes,SET(NO).CurrentSlice); - end; - end; + end + end if dolv if (epi)&&(~isempty(SET(NO).EpiX)) SET(NO).EpiX(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).EpiX(:,timeframes,SET(NO).CurrentSlice); SET(NO).EpiY(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).EpiY(:,timeframes,SET(NO).CurrentSlice); - end; + end else - if (epi)&&(~isempty(SET(NO).RVEpiX)) + if (rvepi)&&(~isempty(SET(NO).RVEpiX)) SET(NO).RVEpiX(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).RVEpiX(:,timeframes,SET(NO).CurrentSlice); SET(NO).RVEpiY(:,timeframes,SET(NO).CurrentSlice+1) = SET(NO).RVEpiY(:,timeframes,SET(NO).CurrentSlice); - end; - end; + end + end SET(NO).CurrentSlice = SET(NO).CurrentSlice+1; SET(NO).StartSlice = SET(NO).CurrentSlice; SET(NO).EndSlice = SET(NO).StartSlice; - if endo - if dolv - switch lvalg - case 'old' - lv('segmentrefineendo_Callback',silent); - case 'new' - lvpeter('segmentrefineendo_Callback',silent); - end - else - rv('segmentrefinervendo_Callback',silent,false); - end; - end; - if epi - if dolv + if dolv + if endo switch lvalg case 'old' lv('segmentrefineendo_Callback',silent); case 'new' lvpeter('segmentrefineendo_Callback',silent); end - end; - end; + end + else + rv('segmentrefinervendo_Callback',silent,false); + end + if dolv && epi + switch lvalg + case 'old' + lv('segmentrefineepi_Callback',silent); + case 'new' + lvpeter('segmentrefineepi_Callback',silent); + end + end if not(silent) - SET(NO).CurrentSlice = SET(NO).CurrentSlice-1; %movetowardsbase undoes this. - segment('movetowardsapex_Callback'); %This really updates graphics correctly - end; -end; + DATA.ViewIM{DATA.CurrentPanel} = []; + drawfunctions('drawno',NO) + end +end %-------------------------------------------------- function copytoalltimeframes_Callback(type,silent,dolv) @@ -4398,7 +4383,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) if nargin<2 silent = false; -end; +end if nargin<3 if isequal(DATA.CurrentTheme,'lv') @@ -4417,7 +4402,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) dolv = false; end end -end; +end @@ -4431,7 +4416,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) endo =1; epi = 1; end -end; +end %check if contour exist in selected slice and timeframe docontinue=true; @@ -4460,7 +4445,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) %ans slices if not(docontinue) tip = DATA.singleframetip; - myfailed(dprintf('%s%s',errmsg,tip)); + myfailed(sprintf('%s%s',errmsg,tip)); return; end @@ -4469,45 +4454,51 @@ function copytoalltimeframes_Callback(type,silent,dolv) if (endo)&&(~isempty(SET(NO).EndoX)) SET(NO).EndoX(:,t,SET(NO).CurrentSlice) = SET(NO).EndoX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); SET(NO).EndoY(:,t,SET(NO).CurrentSlice) = SET(NO).EndoY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); - end; + end else if (endo)&&(~isempty(SET(NO).RVEndoX)) SET(NO).RVEndoX(:,t,SET(NO).CurrentSlice) = SET(NO).RVEndoX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); SET(NO).RVEndoY(:,t,SET(NO).CurrentSlice) = SET(NO).RVEndoY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); - end; - end; + end + end if dolv if (epi)&&(~isempty(SET(NO).EpiY)) SET(NO).EpiX(:,t,SET(NO).CurrentSlice) = SET(NO).EpiX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); SET(NO).EpiY(:,t,SET(NO).CurrentSlice) = SET(NO).EpiY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); - end; + end else if (epi)&&(~isempty(SET(NO).RVEpiY)) SET(NO).RVEpiX(:,t,SET(NO).CurrentSlice) = SET(NO).RVEpiX(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); SET(NO).RVEpiY(:,t,SET(NO).CurrentSlice) = SET(NO).RVEpiY(:,SET(NO).CurrentTimeFrame,SET(NO).CurrentSlice); - end; - end; + end + end end if not(silent) - drawfunctions('drawall'); -end; + drawfunctions('drawpanel',DATA.CurrentPanel); +end %---------------------------------------- -function opensetimagedescription_Callback %#ok +function opensetimagedescription_Callback(frompreviewmenu) %#ok %---------------------------------------- %Open the gui for setting the image type, image view plane and %imaging technique for current image stack global DATA SET NO +if nargin>0 && frompreviewmenu %from context menu + no = segment_main('getclickedpreview'); +else + no = NO; +end + %Initalize DATA.GUI.SetImageDescription = mygui('setimagedescription.fig'); gui = DATA.GUI.SetImageDescription; -gui.NO = NO; +gui.NO = no; [type,viewplane,technique] = segment('imagedescription'); set(gui.handles.listboximagetype,'String',type); @@ -4515,7 +4506,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) set(gui.handles.listboximagingtechnique,'String',technique); %set the parameters -imagetype = SET(NO).ImageType; +imagetype = SET(no).ImageType; allimagetypes = get(gui.handles.listboximagetype,'String'); imagetypenbr = []; for loop = 1:length(allimagetypes) @@ -4532,7 +4523,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) set(gui.handles.listboximagetype,'value',imagetypenbr); end -imageviewplane = SET(NO).ImageViewPlane; +imageviewplane = SET(no).ImageViewPlane; allimageviewplanes = get(gui.handles.listboximageviewplane,'String'); imageviewplanenbr = []; for loop = 1:length(allimageviewplanes) @@ -4549,7 +4540,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) set(gui.handles.listboximageviewplane,'value',imageviewplanenbr); end -imagingtechnique = SET(NO).ImagingTechnique; +imagingtechnique = SET(no).ImagingTechnique; allimagingtechniques = get(gui.handles.listboximagingtechnique,'String'); imagingtechniquenbr = []; for loop = 1:length(allimagingtechniques) @@ -4565,7 +4556,7 @@ function copytoalltimeframes_Callback(type,silent,dolv) else set(gui.handles.listboximagingtechnique,'value',imagingtechniquenbr); end -DATA.setsectorrotation(NO); +DATA.setsectorrotation(no); %------------------------------------ function setimagedescription_Callback %#ok @@ -4573,11 +4564,12 @@ function copytoalltimeframes_Callback(type,silent,dolv) %Set the image type, image view plane and %imaging technique for current image stack -global DATA SET NO +global DATA SET gui = DATA.GUI.SetImageDescription; +no = gui.NO; -if ~isempty(SET(NO).LevelSet) +if ~isempty(SET(no).LevelSet) answer = yesno('If you proceed all 3D segmentation will be removed for the selected stack. Are you sure you want to proceed?'); segment3dp.tools('deleteall_Callback',1) if ~answer @@ -4606,73 +4598,83 @@ function copytoalltimeframes_Callback(type,silent,dolv) return; end if isfield(res,'Image_Type') - SET(NO).ImageType = res.Image_Type; + SET(no).ImageType = res.Image_Type; else temp = get(gui.handles.listboximagetype,'String'); - SET(NO).ImageType = temp{imagetypenbr}; + SET(no).ImageType = temp{imagetypenbr}; end if isfield(res,'Image_View_Plane') - SET(NO).ImageViewPlane = res.Image_View_Plane; + SET(no).ImageViewPlane = res.Image_View_Plane; else temp = get(gui.handles.listboximageviewplane,'String'); - SET(NO).ImageViewPlane = temp{imageviewplanenbr}; + SET(no).ImageViewPlane = temp{imageviewplanenbr}; end if isfield(res,'Imaging_Technique') - SET(NO).ImagingTechnique = res.Imaging_Technique; + SET(no).ImagingTechnique = res.Imaging_Technique; else temp = get(gui.handles.listboximagingtechnique,'String'); - SET(NO).ImagingTechnique = temp{imagingtechniquenbr}; + SET(no).ImagingTechnique = temp{imagingtechniquenbr}; end else temp = get(gui.handles.listboximagetype,'String'); - SET(NO).ImageType = temp{imagetypenbr}; + SET(no).ImageType = temp{imagetypenbr}; temp = get(gui.handles.listboximageviewplane,'String'); - SET(NO).ImageViewPlane = temp{imageviewplanenbr}; + SET(no).ImageViewPlane = temp{imageviewplanenbr}; temp = get(gui.handles.listboximagingtechnique,'String'); - SET(NO).ImagingTechnique = temp{imagingtechniquenbr}; + SET(no).ImagingTechnique = temp{imagingtechniquenbr}; end %set modality based on imaging tecknique -ImTe = SET(NO).ImagingTechnique(1:2); +ImTe = SET(no).ImagingTechnique(1:2); if strcmp(ImTe,'NM') - SET(NO).Modality = 'NM'; + SET(no).Modality = 'NM'; elseif strcmp(ImTe,'MR') - SET(NO).Modality = 'MR'; + SET(no).Modality = 'MR'; elseif strcmp(ImTe,'CT') - SET(NO).Modality = 'CT'; + SET(no).Modality = 'CT'; elseif strcmp(ImTe,'PT') - SET(NO).Modality = 'PT'; + SET(no).Modality = 'PT'; elseif strcmp(ImTe,'US') - SET(NO).Modality = 'US'; + SET(no).Modality = 'US'; elseif strcmp(ImTe,'XR') - SET(NO).Modality = 'XR'; + SET(no).Modality = 'XR'; elseif strcmp(ImTe,'CR') - SET(NO).Modality = 'CR'; + SET(no).Modality = 'CR'; else - SET(NO).Modality = 'OT'; + SET(no).Modality = 'OT'; end %only for tagged imnage stacks -if strcmp(SET(NO).ImageType,'Strain from tagging') - SET(NO).Cyclic = false; +if strcmp(SET(no).ImageType,'Strain from tagging') + SET(no).Cyclic = false; end %close the gui closesetimagedescription_Callback -segment('viewrefreshall_Callback') + +%Update stack name +calcpreview = false; +drawfunctions('drawthumbnails',calcpreview); %----------------------------- -function setheartrate_Callback %#ok +function setheartrate_Callback(frompreviewmenu) %#ok %----------------------------- %Set heart rate of current image stack global SET NO -curhr = num2str(SET(NO).HeartRate); -newhr = str2double(inputdlg('Heart Rate','Enter new value',1,{curhr})); + +if nargin>0 && frompreviewmenu %from context menu + no = segment_main('getclickedpreview'); +else + no = NO; +end + +curhr = num2str(SET(no).HeartRate); +newhr = str2double(myinputdlg('Heart Rate','Enter new value',1,{curhr})); if isempty(newhr) return end if ~isnan(newhr) && newhr >= 0 - SET(NO).HeartRate = newhr; + SET(no).HeartRate = newhr; else myfailed('Invalid heart rate input'); end @@ -4689,6 +4691,55 @@ function copytoalltimeframes_Callback(type,silent,dolv) close(gcf) end +%-------------------------------- +function outstring = maskpatientstrings(instring,patientname,patientid) %#ok +%-------------------------------- +% function to mask patient identity in strings +global SET +try + if nargin < 2 + % no orginal name was provided + if ~isempty(SET) && isfield(SET(1), 'PatientInfo') && isfield(SET(1).PatientInfo, 'Name') + if ~isempty(SET(1).PatientInfo.Name) + patientname = SET(1).PatientInfo.Name; + else + patientname = 'ThereIsNoPatientNameInThisDataSet'; + end + end + elseif isempty(SET) && nargin < 3 + % return when SET is empty and no extra values were provided + outstring = instring; + return + end + if nargin < 3 + % no orginal ID was provided + if ~isempty(SET) && isfield(SET(1), 'PatientInfo') && isfield(SET(1).PatientInfo, 'Name') + if ~isempty(SET(1).PatientInfo.Name) + patientid = SET(1).PatientInfo.ID; + else + patientid = 'ThereIsNoPatientIDInThisDataSet'; + end + end + end + if ~isempty(patientname) + % replace space with '_' + patientname = strrep(patientname,' ','_'); + %check for patientname and patient ID in the provided instring + if contains(instring,patientname,'IgnoreCase',true) + instring = regexprep(instring,patientname,'patientname','ignorecase'); + end + end + if ~isempty(patientid) + patientid = removeinvalidchars(patientid); + patientid = strrep(patientid,':','-'); + if contains(instring,patientid,'IgnoreCase',true) + instring = regexprep(instring,patientid,'patientID','ignorecase'); + end + end +catch +end +outstring = instring; + %-------------------------------- function anonymous_Callback(silent,newname) %#ok %-------------------------------- @@ -4706,20 +4757,20 @@ function anonymous_Callback(silent,newname) %#ok end if not(silent) - if not(yesno('Making data set anonymous is not undoable. This feature will remove subject identity (patient ID and name) on the current .mat files. Are you sure?',[],DATA.GUI.Segment)); + if not(yesno('Making data set anonymous is not undoable. This feature will remove subject identity (patient ID and name) on the current .mat files. Are you sure?',[],DATA.GUI.Segment)) return; - end; + end end if nargin<2 %Ask for new name - newname = inputdlg({'Enter new name for dataset'},'New name',1,{'NoName'}); + newname = myinputdlg({'Enter new name for dataset'},'New name',1,{'NoName'}); if isempty(newname) myfailed('No name entered. Aborted.',DATA.GUI.Segment); return; else newname = newname{1}; - end; + end end %Remove info @@ -4727,8 +4778,8 @@ function anonymous_Callback(silent,newname) %#ok %calculate age since birthdate is removed if (not(isfield(SET(loop).PatientInfo,'Age'))||isempty(SET(loop).PatientInfo.Age))&&... (not(isempty(SET(loop).PatientInfo.BirthDate)) &¬(isempty(SET(loop).PatientInfo.AcquisitionDate))) - age=datenum(SET(loop).PatientInfo.AcquisitionDate,'yyyymmdd')-datenum(SET(loop).PatientInfo.BirthDate,'yyyymmdd'); - SET(loop).PatientInfo.Age=datestr(age,'yy'); + age = datenum(SET(loop).PatientInfo.AcquisitionDate,'yyyymmdd')-datenum(SET(loop).PatientInfo.BirthDate,'yyyymmdd'); + SET(loop).PatientInfo.Age = datestr(age,'yy'); end %remove patientinfo SET(loop).PatientInfo.Name = newname; @@ -4737,12 +4788,17 @@ function anonymous_Callback(silent,newname) %#ok SET(loop).FileName = newname; SET(loop).OrigFileName = newname; SET(loop).PathName = ''; -end; + if isfield(SET(loop),'Report') + % remove report information + SET(loop).Report = []; + end +end if not(silent) mymsgbox('Patient identity removed. Store the file to save the changes.','Done!',DATA.GUI.Segment); - segment('viewrefresh_Callback'); + viewfunctions('setview'); end +segment('updatetitle'); %-------------------------------- @@ -4769,20 +4825,20 @@ function anonymoustotal_Callback(silent,newname) %#ok end if not(silent) - if not(yesno('Making data set anonymous is not undoable. This feature will remove all subject identity and info (patient ID, name, sex, age, length, weight and acquisition date) on the current .mat files. Are you sure?',[],DATA.GUI.Segment)); + if not(yesno('Making data set anonymous is not undoable. This feature will remove all subject identity and info (patient ID, name, sex, age, length, weight and acquisition date) on the current .mat files. Are you sure?',[],DATA.GUI.Segment)) return; - end; + end end if nargin<2 %Ask for new name - newname = inputdlg({'Enter new name for dataset'},'New name',1,{'NoName'}); + newname = myinputdlg({'Enter new name for dataset'},'New name',1,{'NoName'}); if isempty(newname) myfailed('No name entered. Aborted.',DATA.GUI.Segment); return; else newname = newname{1}; - end; + end end %Remove info @@ -4801,10 +4857,48 @@ function anonymoustotal_Callback(silent,newname) %#ok SET(loop).PatientInfo.Weight = ''; SET(loop).PatientInfo.BSA = ''; SET(loop).PatientInfo.Institution = ''; -end; + if isfield(SET(loop),'Report') + % remove report information + SET(loop).Report = []; + end +end if not(silent) mymsgbox('Patient identity and info removed. Store the file to save the changes.','Done!',DATA.GUI.Segment); + viewfunctions('setview'); +end +segment('updatetitle'); + +%-------------------------------- +function anonymouscorrective_Callback(silent,newname) %#ok +%-------------------------------- +%Correction of pseudonymization by removing +%- OrigFileName +%- PathName + +global DATA SET +if nargin<1 + silent=false; +end + +if not(silent) + if not(yesno('This feature will make a correction of previous pseudonymization by removing original filename and pathname on the current .mat files. Are you sure?',[],DATA.GUI.Segment)) + return; + end +end + +%Remove info +for loop =1:length(SET) + SET(loop).OrigFileName = newname; + SET(loop).PathName = ''; + if isfield(SET(loop),'Report') + % remove report information + SET(loop).Report = []; + end +end + +if not(silent) + mymsgbox('Original filename and pathname removed. Store the file to save the changes.','Done!',DATA.GUI.Segment); segment('viewrefresh_Callback'); end @@ -4817,7 +4911,7 @@ function anonymoustotal_Callback(silent,newname) %#ok global DATA SET NO -if yesno('This feature is not undoable. Are you sure?',[],DATA.GUI.Segment); +if yesno('This feature is not undoable. Are you sure?',[],DATA.GUI.Segment) tempnos=NO; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -4831,10 +4925,11 @@ function anonymoustotal_Callback(silent,newname) %#ok SET(NO).IM = max(SET(NO).IM,0); DATA.EndoEdgeDetected = false; DATA.EpiEdgeDetected = false; - segment('makeviewim',DATA.CurrentPanel,NO); + DATA.ViewIM{DATA.CurrentPanel} = []; segment('resetlight_Callback'); - drawfunctions('drawsliceno'); -end; + DATA.ViewIM{DATA.CurrentPanel} = []; + drawfunctions('drawimage',DATA.CurrentPanel); +end %------------------------------- function flip_Callback(dim) @@ -4852,7 +4947,7 @@ function flip_Callback(dim) if not(imissingle) return; end -end; +end disableundo; @@ -4867,8 +4962,6 @@ function flip_Callback(dim) SET(no).PapillaryIM = flip(SET(no).PapillaryIM,dim); end - DATA.ViewIM{DATA.CurrentPanel} = []; - segment('makeviewim',DATA.CurrentPanel,no); %Scar if not(isempty(SET(no).Scar)) @@ -4876,7 +4969,7 @@ function flip_Callback(dim) tempdim = 3; else tempdim = dim; - end; + end SET(no).Scar.IM = flip(SET(no).Scar.IM,tempdim); SET(no).Scar.Auto = flip(SET(no).Scar.Auto,tempdim); SET(no).Scar.Result = flip(SET(no).Scar.Result,tempdim); @@ -4884,7 +4977,7 @@ function flip_Callback(dim) SET(no).Scar.NoReflow = flip(SET(no).Scar.NoReflow,tempdim); SET(no).Scar.MyocardMask = flip(SET(no).Scar.MyocardMask,tempdim); %SET(no).Scar.Undo = flip(SET(no).Scar.Undo,tempdim); - end; + end %MaR if not(isempty(SET(no).MaR)) @@ -4892,27 +4985,32 @@ function flip_Callback(dim) SET(no).MaR.Result = flip(SET(no).MaR.Result,dim); SET(no).MaR.Manual = flip(SET(no).MaR.Manual,dim); SET(no).MaR.MyocardMask = flip(SET(no).MaR.MyocardMask,dim); - end; + end %LevelSet - if not(isempty(SET(no).LevelSet)) + if not(isempty(SET(no).LevelSet)) && isfield(SET(no).LevelSet,'Object') mywarning('Close general segmentation view before continuing.',DATA.GUI.Segment); % stored objects, important to flip stored object before %.BW since levelsetunpack uses the size of .BW and pack does not use %the size - for obj=1:length(SET(no).LevelSet.Object.Ind) + for obj=1:length(SET(no).LevelSet.Object.Ind) if ndims(SET(no).LevelSet.BW)>3 temp=segment3dp.tools('levelsetunpack',obj,no); else temp=segment3dp.tools('levelsetunpack',obj,no); - end; - temp=flip(temp,dim); + end + temp = flip(temp,dim); if ndims(SET(no).LevelSet.BW)>3 [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; + else [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); - end; + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; + end end %Take care of different dimensionality of levelset and gobject @@ -4923,27 +5021,27 @@ function flip_Callback(dim) tempdim = 3; else tempdim = dim; - end; - end; + end + end %resample .BW - SET(no).LevelSet.BW=flip(SET(no).LevelSet.BW,temdim); + SET(no).LevelSet.BW = flip(SET(no).LevelSet.BW,temdim); %resample .Man - SET(no).LevelSet.Man=flip(SET(no).LevelSet.Man,tempdim); + DATA.LevelSet.Man = flip(DATA.LevelSet.Man,tempdim); %clear DATA.LevelSet - segment('cleardatalevelset'); - end; + cleardatalevelset + end %Fix with segmentation for zloop=1:SET(no).ZSize - for tloop=1:SET(no).TSize + for tloop=1:SET(no).TSize segment('checkconsistency',SET(no).CurrentTimeFrame,SET(no).CurrentSlice); - end; - end; + end + end -end; +end %Flip image coordinates switch dim @@ -4967,7 +5065,7 @@ function flip_Callback(dim) %flipped at the same time as z is flipped. SET(no).ImagePosition = SET(no).ImagePosition+zdir*(SET(no).ZSize-1)*... (SET(no).SliceThickness+SET(no).SliceGap); -end; +end %Negate velocity data if necessary if not(isempty(SET(no).Flow)) @@ -4975,29 +5073,29 @@ function flip_Callback(dim) case 1 if isequal(SET(no).Flow.PhaseX,no) SET(no).IM = 1-SET(no).IM; %Negate - end; + end case 2 if isequal(SET(no).Flow.PhaseY,no) SET(no).IM = 1-SET(no).IM; %Negate - end; + end case 3 if isequal(SET(no).Flow.PhaseNo,no) SET(no).IM = 1-SET(no).IM; %Negate - end; + end case 4 %Negate all since reversing time if isequal(SET(no).Flow.PhaseX,no) SET(no).IM = 1-SET(no).IM; %Negate - end; + end if isequal(SET(no).Flow.PhaseY,no) SET(no).IM = 1-SET(no).IM; %Negate - end; + end if isequal(SET(no).Flow.PhaseNo,no) SET(no).IM = 1-SET(no).IM; %Negate - end; - end; + end + end -end; +end %remove Strain tagging analysis if not(isempty(SET(no).StrainTagging)) @@ -5008,6 +5106,10 @@ function flip_Callback(dim) SET(no).StrainTagging = []; end +%Graphical update +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel) + DATA.EndoEdgeDetected = false; DATA.EpiEdgeDetected = false; @@ -5018,10 +5120,8 @@ function flip_Callback(dim) %Need to flip both x and z to maintain a righthand system. flipx_helper; flipz_helper; -segment('updatemodeldisplay'); segment('updatevolume'); -segment('viewrefresh_Callback'); -drawfunctions('drawintersections'); +viewfunctions('setview') %this is the refresh call %Create thumbnails. recreate = true; @@ -5035,10 +5135,8 @@ function flip_Callback(dim) %Need to flip both y and z to maintain a righthand system. flipy_helper; flipz_helper; -segment('updatemodeldisplay'); segment('updatevolume'); -segment('viewrefresh_Callback'); -drawfunctions('drawintersections'); +viewfunctions('setview') %this is the refresh call %Create thumbnails. recreate = true; @@ -5052,10 +5150,8 @@ function flip_Callback(dim) %Need to flip both z and x to maintain a righthand system. flipx_helper; flipz_helper; -segment('updatemodeldisplay'); segment('updatevolume'); -segment('viewrefresh_Callback'); -drawfunctions('drawintersections'); +viewfunctions('setview') %this is the refresh call %----------------------------------- function rotate90right_Callback %#ok @@ -5065,10 +5161,8 @@ function flip_Callback(dim) flipxy_helper; flipy_helper; -segment('updatemodeldisplay'); segment('updatevolume'); -segment('viewrefresh_Callback'); -drawfunctions('drawintersections'); +viewfunctions('setview') %this is the refresh call %Create thumbnails. recreate = true; @@ -5084,47 +5178,47 @@ function flip_Callback(dim) %Make sure magnitude image is current. if ~isempty(SET(NO).Parent) no = SET(NO).Parent; - segment('switchtoimagestack',no); -end; + viewfunctions('switchimagestack',no); +end if ~isempty(SET(NO).EndoX) SET(NO).EndoX = (SET(NO).XSize+1)-SET(NO).EndoX; %maintain rotation dir SET(NO).EndoX = flip(SET(NO).EndoX,1); SET(NO).EndoY = flip(SET(NO).EndoY,1); -end; +end if ~isempty(SET(NO).EpiX) SET(NO).EpiX = (SET(NO).XSize+1)-SET(NO).EpiX; %maintain rotation dir SET(NO).EpiX = flip(SET(NO).EpiX,1); SET(NO).EpiY = flip(SET(NO).EpiY,1); -end; +end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoX = (SET(NO).XSize+1)-SET(NO).RVEndoX; %maintain rotation dir SET(NO).RVEndoX = flip(SET(NO).RVEndoX,1); SET(NO).RVEndoY = flip(SET(NO).RVEndoY,1); -end; +end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiX = (SET(NO).XSize+1)-SET(NO).RVEpiX; %maintain rotation dir SET(NO).RVEpiX = flip(SET(NO).RVEpiX,1); SET(NO).RVEpiY = flip(SET(NO).RVEpiY,1); -end; +end for zloop=1:SET(NO).ZSize for tloop=1:SET(NO).TSize if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinX{tloop,zloop} = (SET(NO).XSize+1)-SET(NO).EndoPinX{tloop,zloop}; - end; + end if ~isempty(SET(NO).EpiPinX) SET(NO).EpiPinX{tloop,zloop} = (SET(NO).XSize+1)-SET(NO).EpiPinX{tloop,zloop}; - end; - end; -end; + end + end +end %Forget about trying to move interp points segmentation('removeallinterp_Callback',true); @@ -5134,17 +5228,17 @@ function flip_Callback(dim) for rloop=1:SET(NO).RoiN SET(NO).Roi(rloop).X = (SET(NO).XSize+1)-SET(NO).Roi(rloop).X; end -end; +end %point if not(isempty(SET(NO).Point)) SET(NO).Point.X = SET(NO).XSize-SET(NO).Point.X+1; -end; +end %measure for loop=1:length(SET(NO).Measure) SET(NO).Measure(loop).X = SET(NO).XSize-SET(NO).Measure(loop).X+1; -end; +end %Flip image data and update flip_Callback(1); @@ -5158,47 +5252,47 @@ function flip_Callback(dim) %Make sure magnitude image is current. if ~isempty(SET(NO).Parent) no = SET(NO).Parent; - segment('switchtoimagestack',no); -end; + viewfunctions('switchimagestack',no) +end if ~isempty(SET(NO).EndoX) SET(NO).EndoY = (SET(NO).YSize+1)-SET(NO).EndoY; %maintain rotation dir SET(NO).EndoX = flip(SET(NO).EndoX,1); SET(NO).EndoY = flip(SET(NO).EndoY,1); -end; +end if ~isempty(SET(NO).EpiX) SET(NO).EpiY = (SET(NO).YSize+1)-SET(NO).EpiY; %maintain rotation dir SET(NO).EpiX = flip(SET(NO).EpiX,1); SET(NO).EpiY = flip(SET(NO).EpiY,1); -end; +end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoY = (SET(NO).YSize+1)-SET(NO).RVEndoY; %maintain rotation dir SET(NO).RVEndoX = flip(SET(NO).RVEndoX,1); SET(NO).RVEndoY = flip(SET(NO).RVEndoY,1); -end; +end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiY = (SET(NO).YSize+1)-SET(NO).RVEpiY; %maintain rotation dir SET(NO).RVEpiX = flip(SET(NO).RVEpiX,1); SET(NO).RVEpiY = flip(SET(NO).RVEpiY,1); -end; +end for zloop=1:SET(NO).ZSize for tloop=1:SET(NO).TSize if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinY{tloop,zloop} = (SET(NO).YSize+1)-SET(NO).EndoPinY{tloop,zloop}; - end; + end if ~isempty(SET(NO).EndoPinY) SET(NO).EpiPinY{tloop,zloop} = (SET(NO).YSize+1)-SET(NO).EpiPinY{tloop,zloop}; - end; - end; -end; + end + end +end %Forget about trying to move interp points segmentation('removeallinterp_Callback',true); @@ -5208,17 +5302,17 @@ function flip_Callback(dim) for rloop=1:SET(NO).RoiN SET(NO).Roi(rloop).Y = (SET(NO).YSize+1)-SET(NO).Roi(rloop).Y; end -end; +end %point if not(isempty(SET(NO).Point)) SET(NO).Point.Y = SET(NO).YSize-SET(NO).Point.Y+1; -end; +end %measure for loop=1:length(SET(NO).Measure) SET(NO).Measure(loop).Y = SET(NO).YSize-SET(NO).Measure(loop).Y+1; -end; +end %rotation center if SET(NO).Rotated @@ -5238,8 +5332,8 @@ function flip_Callback(dim) %Make sure magnitude image is current. if ~isempty(SET(NO).Parent) no = SET(NO).Parent; - segment('switchtoimagestack',no); -end; + viewfunctions('switchimagestack',no) +end SET(NO).CurrentSlice = SET(NO).ZSize-SET(NO).CurrentSlice+1; @@ -5248,22 +5342,22 @@ function flip_Callback(dim) if ~isempty(SET(NO).EndoX) SET(NO).EndoX = SET(NO).EndoX(:,:,ind); SET(NO).EndoY = SET(NO).EndoY(:,:,ind); -end; +end if ~isempty(SET(NO).EpiX) SET(NO).EpiX = SET(NO).EpiX(:,:,ind); SET(NO).EpiY = SET(NO).EpiY(:,:,ind); -end; +end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoX = SET(NO).RVEndoX(:,:,ind); SET(NO).RVEndoY = SET(NO).RVEndoY(:,:,ind); -end; +end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiX = SET(NO).RVEpiX(:,:,ind); SET(NO).RVEpiY = SET(NO).RVEpiY(:,:,ind); -end; +end SET(NO).EndoDraged = SET(NO).EndoDraged(:,ind); @@ -5272,19 +5366,19 @@ function flip_Callback(dim) if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinX = SET(NO).EndoPinX(:,ind); SET(NO).EndoPinY = SET(NO).EndoPinY(:,ind); -end; -if ~isempty(SET(NO).EpiPinY); +end +if ~isempty(SET(NO).EpiPinY) SET(NO).EpiPinX = SET(NO).EpiPinX(:,ind); SET(NO).EpiPinY = SET(NO).EpiPinY(:,ind); -end; +end if ~isempty(SET(NO).RVEndoPinX) SET(NO).RVEndoPinX = SET(NO).RVEndoPinX(:,ind); SET(NO).RVEndoPinY = SET(NO).RVEndoPinY(:,ind); -end; -if ~isempty(SET(NO).RVEpiPinY); +end +if ~isempty(SET(NO).RVEpiPinY) SET(NO).RVEpiPinX = SET(NO).RVEpiPinX(:,ind); SET(NO).RVEpiPinY = SET(NO).RVEpiPinY(:,ind); -end; +end %Forget about trying to move interp points segmentation('removeallinterp_Callback',true); @@ -5294,17 +5388,17 @@ function flip_Callback(dim) for rloop=1:SET(NO).RoiN SET(NO).Roi(rloop).Z = SET(NO).ZSize-SET(NO).Roi(rloop).Z+1; end -end; +end %point if not(isempty(SET(NO).Point)) SET(NO).Point.Z = SET(NO).ZSize-SET(NO).Point.Z+1; -end; +end %measure for loop=1:length(SET(NO).Measure) SET(NO).Measure(loop).Z = SET(NO).ZSize-SET(NO).Measure(loop).Z+1; -end; +end %Flip image data and update flip_Callback(4); @@ -5319,30 +5413,31 @@ function flip_Callback(dim) %Make sure magnitude image is current. if ~isempty(SET(NO).Parent) no = SET(NO).Parent; - segment('switchtoimagestack',no); -end; + viewfunctions('switchimagestack',no) + +end ind = SET(NO).TSize:-1:1; if ~isempty(SET(NO).EndoX) SET(NO).EndoX = SET(NO).EndoX(:,ind,:); SET(NO).EndoY = SET(NO).EndoY(:,ind,:); -end; +end if ~isempty(SET(NO).EpiX) SET(NO).EpiX = SET(NO).EpiX(:,ind,:); SET(NO).EpiY = SET(NO).EpiY(:,ind,:); -end; +end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoX = SET(NO).RVEndoX(:,ind,:); SET(NO).RVEndoY = SET(NO).RVEndoY(:,ind,:); -end; +end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiX = SET(NO).RVEpiX(:,ind,:); SET(NO).RVEpiY = SET(NO).RVEpiY(:,ind,:); -end; +end SET(NO).EndoDraged = SET(NO).EndoDraged(ind,:); SET(NO).EpiDraged = SET(NO).EpiDraged(ind,:); @@ -5352,19 +5447,19 @@ function flip_Callback(dim) if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinX = SET(NO).EndoPinX(ind,:); SET(NO).EndoPinY = SET(NO).EndoPinY(ind,:); -end; +end if ~isempty(SET(NO).EpiPinX) SET(NO).EpiPinX = SET(NO).EpiPinX(ind,:); SET(NO).EpiPinY = SET(NO).EpiPinY(ind,:); -end; +end if ~isempty(SET(NO).RVEndoPinX) SET(NO).RVEndoPinX = SET(NO).RVEndoPinX(ind,:); SET(NO).RVEndoPinY = SET(NO).RVEndoPinY(ind,:); -end; +end if ~isempty(SET(NO).EpiPinX) SET(NO).RVEpiPinX = SET(NO).RVEpiPinX(ind,:); SET(NO).RVEpiPinY = SET(NO).RVEpiPinY(ind,:); -end; +end %Forget about trying to move interp points segmentation('removeallinterp_Callback',true); @@ -5375,21 +5470,21 @@ function flip_Callback(dim) SET(NO).Roi(rloop).Y = SET(NO).Roi(rloop).Y(:,ind); SET(NO).Roi(rloop).T = find(not(isnan(SET(NO).Roi(rloop).X(1,:)))); end -end; +end %point if not(isempty(SET(NO).Point)) SET(NO).Point.T = SET(NO).TSize-SET(NO).Point.T+1; -end; +end %measure, now timeresolved if not(isempty(SET(NO).Measure)) SET(NO).Measure.T = SET(NO).TSize-SET(NO).Measure.T+1; %wors for NaN -end; +end %Flip image data and update flip_Callback(3); -segment('viewrefresh_Callback'); +viewfunctions('setview'); %---------------------------- function flipzt_Callback %#ok @@ -5399,7 +5494,7 @@ function flip_Callback(dim) if not(isempty(SET(NO).Flow)) mywarning('Flip z-t not implemented for flow image stacks. Select view one and flip all connected image stacks manually.',DATA.GUI.Segment); -end; +end permorder = [1 2 4 3]; SET(NO).IM = permute(SET(NO).IM,permorder); @@ -5427,7 +5522,7 @@ function flip_Callback(dim) if isequal(SET(NO).TIncr,0) SET(NO).TIncr = 1/SET(NO).TSize; mywarning('Time increment was 0, now set so that R-R is one second.',DATA.GUI.Segment); -end; +end SET(NO).TimeVector = linspace(0,(SET(NO).TSize-1)*SET(NO).TIncr,SET(NO).TSize); % 180502: Added Update of timevector when switching z and t dimensions SET(NO).CurrentTimeFrame = 1; @@ -5441,22 +5536,22 @@ function flip_Callback(dim) if ~isempty(SET(NO).EndoX) SET(NO).EndoX = permute(SET(NO).EndoX,permorder); SET(NO).EndoY = permute(SET(NO).EndoY,permorder); -end; +end if ~isempty(SET(NO).EpiX) SET(NO).EpiX = permute(SET(NO).EpiX,permorder); SET(NO).EpiY = permute(SET(NO).EpiY,permorder); -end; +end if ~isempty(SET(NO).RVEndoX) SET(NO).RVEndoX = permute(SET(NO).RVEndoX,permorder); SET(NO).RVEndoY = permute(SET(NO).RVEndoY,permorder); -end; +end if ~isempty(SET(NO).RVEpiX) SET(NO).RVEpiX = permute(SET(NO).RVEpiX,permorder); SET(NO).RVEpiY = permute(SET(NO).RVEpiY,permorder); -end; +end SET(NO).EndoDraged = SET(NO).EndoDraged'; SET(NO).EpiDraged = SET(NO).EpiDraged'; @@ -5467,27 +5562,27 @@ function flip_Callback(dim) if ~isempty(SET(NO).EndoPinX) SET(NO).EndoPinX = permute(SET(NO).EndoPinX,permorder); SET(NO).EndoPinY = permute(SET(NO).EndoPinY,permorder); -end; +end if ~isempty(SET(NO).EpiPinX) SET(NO).EpiPinX = permute(SET(NO).EpiPinX,permorder); SET(NO).EpiPinY = permute(SET(NO).EpiPinY,permorder); -end; +end if ~isempty(SET(NO).RVEndoPinX) SET(NO).RVEndoPinX = permute(SET(NO).RVEndoPinX,permorder); SET(NO).RVEndoPinY = permute(SET(NO).RVEndoPinY,permorder); -end; +end if ~isempty(SET(NO).RVEpiPinX) SET(NO).RVEpiPinX = permute(SET(NO).RVEpiPinX,permorder); SET(NO).RVEpiPinY = permute(SET(NO).RVEpiPinY,permorder); -end; +end %Forget about trying to move interp points segmentation('removeallinterp_Callback',true); -if not(isempty(SET(NO).LevelSet)) +if not(isempty(SET(NO).LevelSet)) && isfield(SET(no).LevelSet,'Object') permorder = [1 2 4 3]; mywarning('Close general segmentation view before continuing.',DATA.GUI.Segment); % stored objects, important to flip stored object before @@ -5498,13 +5593,15 @@ function flip_Callback(dim) temp=segment3dp.tools('levelsetunpack',obj,NO); temp=permute(temp,permorder); [SET(NO).LevelSet.Object.Ind{obj},SET(NO).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(NO).LevelSet.Object.Cut{obj} = []; + SET(NO).LevelSet.Object.Deform{obj} = []; end %resample .BW - SET(NO).LevelSet.BW=permute(SET(NO).LevelSet.BW,permorder); + SET(NO).LevelSet.BW = permute(SET(NO).LevelSet.BW,permorder); %resample .Man - SET(NO).LevelSet.Man=permute(SET(NO).LevelSet.Man,permorder); + DATA.LevelSet.Man = permute(DATA.LevelSet.Man,permorder); %slice if size(SET(NO).LevelSet.BW,4)>1 @@ -5521,14 +5618,14 @@ function flip_Callback(dim) SET(NO).LevelSet.View.GZoomState=[]; %clear DATA.LevelSet - segment('cleardatalevelset'); -end; + cleardatalevelset +end %roi if SET(NO).RoiN>0 mywarning('Flip in z-t of ROI''s not implemented.',DATA.GUI.Segment); roi('roiclearall_Callback'); -end; +end %point if not(isempty(SET(NO).Point)) @@ -5538,9 +5635,9 @@ function flip_Callback(dim) else [SET(NO).Point.T(loop),SET(NO).Point.Z(loop)] = flipvars(... SET(NO).Point.T(loop),SET(NO).Point.Z(loop)); - end; - end; -end; + end + end +end %measure now time resolved JU if not(isempty(SET(NO).Measure)) @@ -5550,20 +5647,19 @@ function flip_Callback(dim) else [SET(NO).Measure(loop).T,SET(NO).Measure(loop).Z] = flipvars(... SET(NO).Measure(loop).T,SET(NO).Measure(loop).Z); - end; - end; + end + end % measureclearall_Callback; -end; +end if not(isempty(SET(NO).Scar)) myfailed('Flip z-t is not implemented with scar data present. Scar data removed.',DATA.GUI.Segment); SET(NO).Scar = []; -end; +end segment('updatevolume'); -segment('makeviewim',DATA.CurrentPanel,NO); -segment('updatemodeldisplay'); -segment('viewrefresh_Callback'); +DATA.ViewIM{DATA.CurrentPanel} = []; +viewfunctions('setview'); %-------------------------- function flipxy_helper @@ -5575,7 +5671,7 @@ function flip_Callback(dim) nos = SET(NO).Linked; %--- Loop over image stacks -for no = nos; +for no = nos SET(no).IM = permute(SET(no).IM,[2 1 3 4]); SET(no).XSize = size(SET(no).IM,1); SET(no).YSize = size(SET(no).IM,2); @@ -5592,19 +5688,19 @@ function flip_Callback(dim) %endo,epi,roi if ~isempty(SET(NO).EndoX) [SET(no).EndoX,SET(no).EndoY] = flipvars(SET(no).EndoX,SET(no).EndoY); - end; + end if ~isempty(SET(NO).EpiX) [SET(no).EpiX,SET(no).EpiY] = flipvars(SET(no).EpiX,SET(no).EpiY); - end; + end if ~isempty(SET(NO).RVEndoX) [SET(no).RVEndoX,SET(no).RVEndoY] = flipvars(SET(no).RVEndoX,SET(no).RVEndoY); - end; + end if ~isempty(SET(NO).RVEpiX) [SET(no).RVEpiX,SET(no).RVEpiY] = flipvars(SET(no).RVEpiX,SET(no).RVEpiY); - end; + end [SET(no).EndoPinX,SET(no).EndoPinY] = flipvars(SET(no).EndoPinX,SET(no).EndoPinY); [SET(no).EpiPinX,SET(no).EpiPinY] = flipvars(SET(no).EpiPinX,SET(no).EpiPinY); @@ -5628,7 +5724,7 @@ function flip_Callback(dim) %SET(no).Scar.Undo = permute(SET(no).Scar.Undo,permorder); SET(no).Scar.MyocardMask = permute(SET(no).Scar.MyocardMask,permorder); SET(no).Scar.NoReflow = permute(SET(no).Scar.NoReflow,permorder); - end; + end %MaR if not(isempty(SET(no).MaR)) @@ -5637,7 +5733,7 @@ function flip_Callback(dim) SET(no).MaR.Result = permute(SET(no).MaR.Result,permorder); SET(no).MaR.Manual = permute(SET(no).MaR.Manual,permorder); SET(no).MaR.MyocardMask = permute(SET(no).MaR.MyocardMask,permorder); - end; + end %LevelSet if not(isempty(SET(no).LevelSet)) @@ -5652,20 +5748,24 @@ function flip_Callback(dim) temp=segment3dp.tools('levelsetunpack',obj,no); else temp=segment3dp.tools('levelsetunpack',obj,no); - end; + end temp=permute(temp,permorder); if ndims(SET(no).LevelSet.BW)>3 [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; else [SET(no).LevelSet.Object.Ind{obj},SET(no).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); - end; + SET(no).LevelSet.Object.Cut{obj} = []; + SET(no).LevelSet.Object.Deform{obj} = []; + end end %resample .BW - SET(no).LevelSet.BW=permute(SET(no).LevelSet.BW,permorder); + SET(no).LevelSet.BW = permute(SET(no).LevelSet.BW,permorder); %resample .Man - SET(no).LevelSet.Man=permute(SET(no).LevelSet.Man,permorder); + DATA.LevelSet.Man = permute(DATA.LevelSet.Man,permorder); %slice if size(SET(no).LevelSet.BW,4)>1 @@ -5682,23 +5782,23 @@ function flip_Callback(dim) SET(no).LevelSet.View.GZoomState=[]; %clear DATA.LevelSet - segment('cleardatalevelset'); + cleardatalevelset end %point,measure if not(isempty(SET(no).Point)) [SET(no).Point.X,SET(no).Point.Y] = flipvars(SET(no).Point.X,SET(no).Point.Y); - end; + end for loop=1:length(SET(no).Measure) [SET(no).Measure(loop).X,SET(no).Measure(loop).Y] = flipvars(SET(no).Measure(loop).X,SET(no).Measure(loop).Y); - end; + end %Flip phase directions if not(isempty(SET(no).Flow)) temp = SET(no).Flow.PhaseX; SET(no).Flow.PhaseX = SET(no).Flow.PhaseY; SET(no).Flow.PhaseY = temp; - end; + end %Coordinates %SET(no).ImagePosition = SET(no).ImagePosition+... @@ -5708,7 +5808,7 @@ function flip_Callback(dim) SET(no).ImageOrientation(1:3) = orient(4:6); SET(no).ImageOrientation(4:6) = orient(1:3); -end; %loop over image stacks +end %loop over image stacks DATA.ViewIM{DATA.CurrentPanel} = []; @@ -5718,18 +5818,18 @@ function flip_Callback(dim) %Interchange z & x of current image stack. Takes care of segmentation. global DATA SET NO -if ~yesno('Warning, this will clear measurement and segmentation if present, (except general segmentation). Are you sure?',[],DATA.GUI.Segment); +if ~yesno('Warning, this will clear measurement and segmentation if present, (except general segmentation). Are you sure?',[],DATA.GUI.Segment) return; -end; +end if ~isempty(SET(NO).Flow) mywarning('This is not implemented for flow images, you need to run it on each flow component',DATA.GUI.Segment); -end; +end if (SET(NO).SliceThickness+SET(NO).SliceGap)<0 myfailed('Zero or negative slice thickness.',DATA.GUI.Segment); return; -end; +end SET(NO).IM = permute(SET(NO).IM,[4 2 3 1]); SET(NO).IM = flip(SET(NO).IM,1); @@ -5747,10 +5847,10 @@ function flip_Callback(dim) SET(NO).OrgZSize = temp; %Clear segmentation -segment('segmentclearall_Callback',true); +callbackfunctions('segmentclearall_Callback',true); SET(NO).Scar = []; %LevelSet is not cleared and thuse need to be flipped -if not(isempty(SET(NO).LevelSet)) +if not(isempty(SET(NO).LevelSet)) && isfield(SET(no).LevelSet,'Object') permorder = [4 2 3 1]; mywarning('Close general segmentation view before continuing.',DATA.GUI.Segment); @@ -5761,16 +5861,18 @@ function flip_Callback(dim) temp = segment3dp.tools('levelsetunpack',obj,NO); temp = permute(temp,permorder); temp = flip(temp,1); - [SET(NO).LevelSet.Object.Ind{obj},SET(NO).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + [SET(NO).LevelSet.Object.Ind{obj},SET(NO).LevelSet.Object.Int{obj}] = segment3dp.tools('levelsetpack',temp); + SET(NO).LevelSet.Object.Cut{obj} = []; + SET(NO).LevelSet.Object.Deform{obj} = []; end %resample .BW temp = permute(SET(NO).LevelSet.BW,permorder); - SET(NO).LevelSet.BW=flip(temp,1); + SET(NO).LevelSet.BW = flip(temp,1); %resample .Man - temp = permute(SET(NO).LevelSet.Man,permorder); - SET(NO).LevelSet.Man = flip(temp,1); + temp = permute(DATA.LevelSet.Man,permorder); + DATA.LevelSet.Man = flip(temp,1); %slice SET(NO).LevelSet.View.RSlice = round(size(SET(NO).LevelSet.BW,3)/2); @@ -5783,7 +5885,9 @@ function flip_Callback(dim) SET(NO).LevelSet.View.GZoomState = []; %clear DATA.LevelSet - segment('cleardatalevelset'); + cleardatalevelset + + segment3dp.tools('updatergbsliders'); end %point @@ -5791,7 +5895,7 @@ function flip_Callback(dim) [SET(NO).Point.X,SET(NO).Point.Z] = flipvars(SET(NO).Point.X,SET(NO).Point.Z); SET(NO).Point.Z = round(SET(NO).Point.Z); SET(NO).Point.X = SET(NO).XSize - SET(NO).Point.X + 1; -end; +end %delete measure SET(NO).Measure=[]; @@ -5810,17 +5914,13 @@ function flip_Callback(dim) %z^~ = xdir; SET(NO).ImagePosition = oldpos.... -zdir*(SET(NO).XSize-1)*SET(NO).ResolutionX; -% +xdir*(1)*(SET(NO).SliceThickness+SET(NO).SliceGap).... -% +ydir*(1)*SET(NO).ResolutionY... SET(NO).NormalZoomState = []; SET(NO).MontageZoomState = []; SET(NO).MontageRowZoomState = []; -segment('makeviewim',DATA.CurrentPanel,NO); -segment('updatemodeldisplay'); -%drawintersections; -drawfunctions('drawimageno'); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimage',DATA.CurrentPanel); %Create thumbnails. recreate = true; @@ -5838,12 +5938,16 @@ function enableundo(no) segment('stopmovie_Callback'); -if nargin==0 +if (nargin==0) || isempty(no) no = NO; -end; +end + +% write +if ~isempty(SET(no).Parent) + no = SET(no).Parent; +end DATA.NeedToSave = true; -set(DATA.Handles.filesaveicon,'enable','on'); %Increase pointer try @@ -5852,17 +5956,17 @@ function enableundo(no) else DATA.UndoN = zeros(1,length(SET)); DATA.UndoN(no) = 1; - end; + end catch %#ok DATA.UndoN = zeros(1,length(SET)); DATA.UndoN(no) = 1; -end; +end %Check if larger than UndoHistory if DATA.UndoN(no)>DATA.Pref.UndoHistory DATA.Undo(no,1:(DATA.Pref.UndoHistory-1)) = DATA.Undo(no,2:end); DATA.UndoN(no) = DATA.Pref.UndoHistory; -end; +end %Store DATA.Undo(no,DATA.UndoN(no)).EndoXBackup = SET(no).EndoX; @@ -5873,18 +5977,10 @@ function enableundo(no) DATA.Undo(no,DATA.UndoN(no)).EpiYBackup = SET(no).EpiY; DATA.Undo(no,DATA.UndoN(no)).RVEpiXBackup = SET(no).RVEpiX; DATA.Undo(no,DATA.UndoN(no)).RVEpiYBackup = SET(no).RVEpiY; -DATA.Undo(no,DATA.UndoN(no)).EndoPinXBackup = SET(no).EndoPinX; -DATA.Undo(no,DATA.UndoN(no)).EndoPinYBackup = SET(no).EndoPinY; -DATA.Undo(no,DATA.UndoN(no)).EpiPinXBackup = SET(no).EpiPinX; -DATA.Undo(no,DATA.UndoN(no)).EpiPinYBackup = SET(no).EpiPinY; DATA.Undo(no,DATA.UndoN(no)).EndoInterpXBackup = SET(no).EndoInterpX; DATA.Undo(no,DATA.UndoN(no)).EndoInterpYBackup = SET(no).EndoInterpY; DATA.Undo(no,DATA.UndoN(no)).EpiInterpXBackup = SET(no).EpiInterpX; DATA.Undo(no,DATA.UndoN(no)).EpiInterpYBackup = SET(no).EpiInterpY; -DATA.Undo(no,DATA.UndoN(no)).RVEndoPinXBackup = SET(no).RVEndoPinX; -DATA.Undo(no,DATA.UndoN(no)).RVEndoPinYBackup = SET(no).RVEndoPinY; -DATA.Undo(no,DATA.UndoN(no)).RVEpiPinXBackup = SET(no).RVEpiPinX; -DATA.Undo(no,DATA.UndoN(no)).RVEpiPinYBackup = SET(no).RVEpiPinY; DATA.Undo(no,DATA.UndoN(no)).RVEndoInterpXBackup = SET(no).RVEndoInterpX; DATA.Undo(no,DATA.UndoN(no)).RVEndoInterpYBackup = SET(no).RVEndoInterpY; DATA.Undo(no,DATA.UndoN(no)).RVEpiInterpXBackup = SET(no).RVEpiInterpX; @@ -5939,9 +6035,7 @@ function disableundo(no) if nargin==0 no = NO; -end; - -set(DATA.Handles.undosegmentationicon,'enable','off'); +end if ~isempty(DATA.Undo) DATA.UndoN(no) = 0; @@ -5950,8 +6044,7 @@ function disableundo(no) % functions have been called, and then the NeedToSave bit should be % flipped, so we know there are unsaved things that have happened. DATA.NeedToSave=true; - set(DATA.Handles.filesaveicon,'enable','on'); -end; +end %-------------------------- function seted_Callback %#ok @@ -5977,15 +6070,15 @@ function disableundo(no) function autoesed_Callback(silent,no) %#ok %------------------------------------- %Autodetect and store ED, & ES. -global SET NO +global SET NO DATA if nargin==0 silent = false; -end; +end if nargin<2 no = NO; -end; +end calcfunctions('calcvolume',no); @@ -6020,7 +6113,7 @@ function autoesed_Callback(silent,no) %#ok SET(no).EF = SET(no).SV/SET(no).EDV; %Ejection fraction else SET(no).EF = 0; -end; +end %RV if SET(no).EDT==1 && SET(no).EST==1 @@ -6043,7 +6136,7 @@ function autoesed_Callback(silent,no) %#ok SET(no).RVEF = SET(no).RVSV/SET(no).RVEDV; %Ejection fraction else SET(no).RVEF = 0; -end; +end %also check for imageviewplane imvpcell={'Short-axis','Transversal','2CH','3CH','4CH','Flow'}; @@ -6062,7 +6155,8 @@ function autoesed_Callback(silent,no) %#ok if not(silent) segment('updatevolume'); -end; +end +DATA.updatetimebaraxes; %---------------------------------------- function viewpatientinfo_Callback(arg,no) @@ -6074,11 +6168,9 @@ function viewpatientinfo_Callback(arg,no) delete(gcbf) return end -set(DATA.Handles.patientinfoicon,'state','off'); - if not(DATA.DataLoaded) return; -end; +end gui = DATA.GUI.PatientInfo; @@ -6087,7 +6179,7 @@ function viewpatientinfo_Callback(arg,no) if nargin < 1 arg = 'init'; end -end; +end switch arg case 'init' @@ -6108,13 +6200,15 @@ function viewpatientinfo_Callback(arg,no) set(gui.handles.idedit,'String',SET(gui.no).PatientInfo.ID); set(gui.handles.birthdateedit,'String',SET(gui.no).PatientInfo.BirthDate); set(gui.handles.acquisitiondateedit,'String',SET(gui.no).PatientInfo.AcquisitionDate); - set(gui.handles.ageedit,'String',SET(gui.no).PatientInfo.Age); + [agedigit,ageunit] = calcfunctions('calcagewithunits',SET(gui.no).PatientInfo.Age); + set(gui.handles.patientagetext,'String',['(',ageunit,')']); + set(gui.handles.ageedit,'String',agedigit); set(gui.handles.lengthedit,'String',SET(gui.no).PatientInfo.Length); set(gui.handles.weightedit,'String',SET(gui.no).PatientInfo.Weight); set(gui.handles.bsaedit,'String',SET(gui.no).PatientInfo.BSA); if isempty(SET(gui.no).PatientInfo.Sex) SET(gui.no).PatientInfo.Sex = '-'; - end; + end switch lower(SET(gui.no).PatientInfo.Sex(1)) case 'm' set(gui.handles.sexlistbox,'value',1); @@ -6125,7 +6219,7 @@ function viewpatientinfo_Callback(arg,no) otherwise set(gui.handles.sexlistbox,'value',3); SET(gui.no).PatientInfo.Sex = '-'; - end; + end segment('updatetitle'); case 'nameedit' s = mygetedit(gui.handles.nameedit); @@ -6138,27 +6232,47 @@ function viewpatientinfo_Callback(arg,no) case 'birthdateedit' s = mygetedit(gui.handles.birthdateedit); SET(gui.no).PatientInfo.BirthDate = s; + %check birthdate, age and acquisition date consistency + if not(isempty(SET(gui.no).PatientInfo.AcquisitionDate)) && not(isempty(SET(gui.no).PatientInfo.Age)) + [agedigitnew,ageunitnew] = calcfunctions('calcagefrombirthdate',SET(gui.no).PatientInfo.BirthDate, SET(gui.no).PatientInfo.AcquisitionDate); + [agedigitold,ageunitold] = calcfunctions('calcagewithunits',SET(gui.no).PatientInfo.Age); + if not((ageunitnew == ageunitold(1)) && (agedigitnew == agedigitold)) + % something went wrong in the setting + mywarning(dprintf('Birth date and age are not consitent.\nSetting age to the value corresponding Acqusition Date - Birth Date.')); + SET(gui.no).PatientInfo.Age = calcfunctions('calcageyearfraction',agedigitnew,ageunitnew); + end + end viewpatientinfo_Callback('update'); case 'ageedit' s = mygetedit(gui.handles.ageedit); n = str2double(s); if not(isnan(n)) SET(gui.no).PatientInfo.Age = n; - end; + %check birthdate, age and acquisition date consistency + if not(isempty(SET(gui.no).PatientInfo.AcquisitionDate)) && not(isempty(SET(gui.no).PatientInfo.BirthDate)) + [agedigitnew,ageunitnew] = calcfunctions('calcagefrombirthdate',SET(gui.no).PatientInfo.BirthDate, SET(gui.no).PatientInfo.AcquisitionDate); + [agedigitold,ageunitold] = calcfunctions('calcagewithunits',SET(gui.no).PatientInfo.Age); + if not((ageunitnew == ageunitold(1)) && (agedigitnew == agedigitold)) + % something went wrong in the setting + mywarning(dprintf('Birth date and age are not consitent.\nSetting age to the value corresponding Acqusition Date - Birth Date.')); + SET(gui.no).PatientInfo.Age = calcfunctions('calcageyearfraction',agedigitnew,ageunitnew); + end + end + end viewpatientinfo_Callback('update'); case 'weightedit' s = mygetedit(gui.handles.weightedit); n = str2double(s); if not(isnan(n)) SET(gui.no).PatientInfo.Weight = n; - end; + end viewpatientinfo_Callback('update'); case 'lengthedit' s = mygetedit(gui.handles.lengthedit); n = str2double(s); if not(isnan(n)) SET(gui.no).PatientInfo.Length = n; - end; + end viewpatientinfo_Callback('update'); case 'sexlistbox' temp = 'MF-'; @@ -6168,7 +6282,7 @@ function viewpatientinfo_Callback(arg,no) temp = SET(gui.no).PatientInfo; for no=1:length(SET) SET(no).PatientInfo = temp; - end; + end mymsgbox('Information applied to all image stacks.','Done!',DATA.GUI.Segment); case 'close' mymsgbox('Save dataset in order to keep changes to patient info.'); @@ -6183,11 +6297,11 @@ function viewpatientinfo_Callback(arg,no) DATA.GUI.PatientInfo = close(DATA.GUI.PatientInfo); catch %#ok delete(gui.fig); - end; + end otherwise myfailed(dprintf('Unknown argument %s to patientinfo',arg),DATA.GUI.Segment); return; -end; +end %----------------------------- function [a,b] = flipvars(b,a) @@ -6243,37 +6357,37 @@ function translatecontour_helper(dx,dy,translateimage) slice = SET(no).StartSlice:SET(no).EndSlice; if isempty(slice) slice = SET(no).CurrentSlice; -end; +end %Endo -if ~isempty(SET(no).EndoX); +if ~isempty(SET(no).EndoX) SET(no).EndoX(:,:,slice) = SET(no).EndoX(:,:,slice)+dx; SET(no).EndoY(:,:,slice) = SET(no).EndoY(:,:,slice)+dy; -end; +end %Epi -if ~isempty(SET(no).EpiX); +if ~isempty(SET(no).EpiX) SET(no).EpiX(:,:,slice) = SET(no).EpiX(:,:,slice)+dx; SET(no).EpiY(:,:,slice) = SET(no).EpiY(:,:,slice)+dy; -end; +end %RVEndo -if ~isempty(SET(no).RVEndoX); +if ~isempty(SET(no).RVEndoX) SET(no).RVEndoX(:,:,slice) = SET(no).RVEndoX(:,:,slice)+dx; SET(no).RVEndoY(:,:,slice) = SET(no).RVEndoY(:,:,slice)+dy; -end; +end %RVEpi -if ~isempty(SET(no).RVEpiX); +if ~isempty(SET(no).RVEpiX) SET(no).RVEpiX(:,:,slice) = SET(no).RVEpiX(:,:,slice)+dx; SET(no).RVEpiY(:,:,slice) = SET(no).RVEpiY(:,:,slice)+dy; -end; +end if (~isempty(SET(no).EndoInterpX)) for tloop = 1:SET(no).TSize for zloop = slice %Endo-Interp - if ~isempty(SET(no).EndoInterpX{tloop,zloop}); + if ~isempty(SET(no).EndoInterpX{tloop,zloop}) SET(no).EndoInterpX{tloop,zloop} = SET(no).EndoInterpX{tloop,zloop}+dx; SET(no).EndoInterpY{tloop,zloop} = SET(no).EndoInterpY{tloop,zloop}+dy; end @@ -6284,7 +6398,7 @@ function translatecontour_helper(dx,dy,translateimage) for tloop = 1:SET(no).TSize for zloop = slice %Endo-Interp - if ~isempty(SET(no).EpiInterpX{tloop,zloop}); + if ~isempty(SET(no).EpiInterpX{tloop,zloop}) SET(no).EpiInterpX{tloop,zloop} = SET(no).EpiInterpX{tloop,zloop}+dx; SET(no).EpiInterpY{tloop,zloop} = SET(no).EpiInterpY{tloop,zloop}+dy; end @@ -6295,7 +6409,7 @@ function translatecontour_helper(dx,dy,translateimage) for tloop = 1:SET(no).TSize for zloop = slice %RVEndo-Interp - if ~isempty(SET(no).RVEndoInterpX{tloop,zloop}); + if ~isempty(SET(no).RVEndoInterpX{tloop,zloop}) SET(no).RVEndoInterpX{tloop,zloop} = SET(no).RVEndoInterpX{tloop,zloop}+dx; SET(no).RVEndoInterpY{tloop,zloop} = SET(no).RVEndoInterpY{tloop,zloop}+dy; end @@ -6306,7 +6420,7 @@ function translatecontour_helper(dx,dy,translateimage) for tloop = 1:SET(no).TSize for zloop = slice %RVEndo-Interp - if ~isempty(SET(no).RVEpiInterpX{tloop,zloop}); + if ~isempty(SET(no).RVEpiInterpX{tloop,zloop}) SET(no).RVEpiInterpX{tloop,zloop} = SET(no).RVEpiInterpX{tloop,zloop}+dx; SET(no).RVEpiInterpY{tloop,zloop} = SET(no).RVEpiInterpY{tloop,zloop}+dy; end @@ -6320,9 +6434,9 @@ function translatecontour_helper(dx,dy,translateimage) if (SET(no).Roi(loop).Z>=slice(1)) && (SET(no).Roi(loop).Z<=slice(end)) SET(no).Roi(loop).X = SET(no).Roi(loop).X+dx; SET(no).Roi(loop).Y = SET(no).Roi(loop).Y+dy; - end; - end; -end; + end + end +end %Measurements if ~isempty(SET(no).Measure) @@ -6330,9 +6444,9 @@ function translatecontour_helper(dx,dy,translateimage) if (SET(no).Measure(loop).Z(1)>=slice(1)) && (SET(no).Measure(loop).Z(2)<=slice(end)) SET(no).Measure(loop).X = SET(no).Measure(loop).X+dx; SET(no).Measure(loop).Y = SET(no).Measure(loop).Y+dy; - end; - end; -end; + end + end +end %Point if ~isempty(SET(no).Point) @@ -6340,9 +6454,9 @@ function translatecontour_helper(dx,dy,translateimage) if (SET(no).Point.Z(loop)>=slice(1)) && (SET(no).Point.Z(loop)<=slice(end)) SET(no).Point.X(loop) = SET(no).Point.X(loop)+dx; SET(no).Point.Y(loop) = SET(no).Point.Y(loop)+dy; - end; - end; -end; + end + end +end if translateimage %--- Image @@ -6354,22 +6468,19 @@ function translatecontour_helper(dx,dy,translateimage) y = translatecontours_helper(y); SET(no).IM(:,:,:,slice) = SET(no).IM(x,y,:,slice); -end; +end -segment('makeviewim',DATA.CurrentPanel,no); +DATA.ViewIM{DATA.CurrentPanel} = []; -%Update screen -drawfunctions('viewupdatetextposition'); -drawfunctions('viewupdateannotext'); -drawfunctions('drawimagepanel',DATA.CurrentPanel); -drawfunctions('updatenopanels',no); + %Update screen +drawfunctions('drawpanel',DATA.CurrentPanel); viewpanels = DATA.ViewPanels; for loop = 1:length(viewpanels) if viewpanels(loop)>0 - drawfunctions('updateintersectionpoints',loop); - end; -end; + drawfunctions('drawintersections',loop); + end +end %---------------------------------- function setcolormap_Callback(type,no) %#ok @@ -6414,8 +6525,8 @@ function setcolormap_Callback(type,no) %#ok cmap(:,3) = interp1(1:length(tempmap),tempmap(:,3),linspace(1,length(tempmap),n))'; SET(no).Colormap = cmap; %set contrast and brightness - window = 1400; %widht - level = 1300; %center + window =3000; %1400, widht + level =1500; %1300, center [contrast, brightness] = calcfunctions('win2con',window,level); SET(no).IntensityMapping.Contrast = contrast; SET(no).IntensityMapping.Brightness = brightness; @@ -6465,8 +6576,8 @@ function setcolormap_Callback(type,no) %#ok cmap(:,3) = interp1(1:length(tempmap),tempmap(:,3),linspace(1,length(tempmap),n))'; SET(no).Colormap = cmap; %set contrast and brightness - window = 50; %widht - level = 25; %center + window = 80; %widht + level = 45; %center [contrast, brightness] = calcfunctions('win2con',window,level); SET(no).IntensityMapping.Contrast = contrast; SET(no).IntensityMapping.Brightness = brightness; @@ -6492,16 +6603,24 @@ function setcolormap_Callback(type,no) %#ok otherwise myfailed('Unknown colormap',DATA.GUI.Segment); return; -end; +end + panelstodo = find(DATA.ViewPanels==no); + for panel=panelstodo - segment('makeviewim',panel,no); + if DATA.GUISettings.ShowColorbar + createfunctions('addcolorbar',panel) + end + DATA.ViewIM{panel} = []; end + +drawfunctions('drawno',no) + recalc=1; updatedslider=0; drawfunctions('drawthumbnails',recalc,updatedslider); -drawfunctions('drawcontrastimage',no); %drawfunctions('drawall',DATA.ViewMatrix); +% drawfunctions('drawcontrastimage',no); %drawfunctions('drawall',DATA.ViewMatrix); %------------------------------- function slidingaverage_Callback %#ok @@ -6514,10 +6633,10 @@ function setcolormap_Callback(type,no) %#ok n = 10; f = single(repmat(1/n,[1 1 n])); h = waitbar(0,'Please wait.'); -for zloop = 1:SET(NO).ZSize; +for zloop = 1:SET(NO).ZSize SET(NO).IM(:,:,:,zloop) = econv3(SET(NO).IM(:,:,:,zloop),f); waitbar(zloop/SET(NO).ZSize,h); -end; +end close(h); %----------------------------------------- @@ -6530,9 +6649,9 @@ function setcolormap_Callback(type,no) %#ok global SET NO DATA -if not(yesno('Image enhancement is not undoable. Are you sure?',[],DATA.GUI.Segment)); +if not(yesno('Image enhancement is not undoable. Are you sure?',[],DATA.GUI.Segment)) return; -end; +end totalnumsteps =SET(NO).TSize*SET(NO).ZSize ; @@ -6545,10 +6664,11 @@ function setcolormap_Callback(type,no) %#ok numsteps = numsteps+1; waitbar(numsteps/totalnumsteps,h); SET(no).IM(:,:,tloop,zloop) = adapthisteq(SET(no).IM(:,:,tloop,zloop)); - end; -end; + end +end close(h); -drawfunctions('drawall'); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimage',DATA.CurrentPanel); %-------------------------------- function unlinkimages_Callback %#ok @@ -6560,19 +6680,19 @@ function setcolormap_Callback(type,no) %#ok no = NO; if ~isempty(SET(NO).Parent) no = SET(NO).Parent; -end; +end linked = SET(no).Linked; for loop = 1:length(linked) SET(linked(loop)).Parent = []; SET(linked(loop)).Children = []; % Just to be sure SET(linked(loop)).Linked = linked(loop); -end; +end SET(no).Parent = []; SET(no).Children = []; SET(no).Linked = no; -segment('viewrefresh_Callback'); +viewfunctions('setview'); %------------------------------------------------------------ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) @@ -6626,26 +6746,22 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) for loop = 1:4 if flipv(loop) SET(no).IM = flip(SET(no).IM,loop); - end; -end; - -%Calculate the preview -sliderupdated = false; -calculatepreview = true; -drawfunctions('drawthumbnails',calculatepreview,sliderupdated); -segment('switchtoimagestack',no); + end +end %Clear segmentation and other stuff -segment('segmentclearall_Callback',true); +callbackfunctions('segmentclearall_Callback',true); SET(no).Scar = []; %Clear scar SET(no).LevelSet = []; %Clear levelset -annotationpoint('pointclearall_helper',no); %Clear points +% callbackfunctions('pointclearall_helper',no); %Clear points +callbackfunctions('pointclearall_Callback'); SET(no).PapillaryIM = []; SET(no).Measure = []; roi('roireset',no); %reset ROI's -SET(no).StartSlice = 1; -SET(no).EndSlice = 1; -SET(no).CurrentSlice = round(SET(no).ZSize/2); +currentslice = round(SET(no).ZSize/2); +SET(no).StartSlice = currentslice; +SET(no).EndSlice = currentslice; +SET(no).CurrentSlice = currentslice; SET(no).Strain = []; SET(no).StrainTagging = []; SET(no).Stress = []; @@ -6653,6 +6769,13 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) SET(no).T2 = []; SET(no).ECV = []; +%Calculate the preview +sliderupdated = false; +calculatepreview = true; +viewfunctions('switchimagestack',no); +viewfunctions('switchslice',0); +drawfunctions('drawthumbnails',calculatepreview,sliderupdated); + %------------------------------------------------------ function ok = orthogonalresamplecheck(no,dir1,dir2,str) %------------------------------------------------------ @@ -6665,28 +6788,28 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) if ~yesno('This will clear all segmentation and measurements. Are you sure?') return; -end; +end %Check it is correct direction if (acos(abs(dir1.*SET(no).ImageOrientation(1:3)))*180/pi)>10 myfailed(sprintf('Current image stack is not a %s stack.',str)); return; -end; +end if (acos((dir2.*SET(no).ImageOrientation(4:6)))*180/pi)>10 myfailed(sprintf('Current image stack is not a %s stack.',str)); return; -end; +end if ~isempty(SET(no).Flow) myfailed('Can not resample flow image stack.'); return; -end; +end if (SET(no).XSize<10) || (SET(no).YSize<10) || (SET(no).ZSize<10) myfailed('Can resample slices with slices.'); return; -end; +end %So far good! ok = true; @@ -6700,9 +6823,9 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) global SET NO %1 0 0 0 1 0 -if ~orthogonalresamplecheck(NO,[1 0 0],[0 1 0],'transversal'); +if ~orthogonalresamplecheck(NO,[1 0 0],[0 1 0],'transversal') return; -end; +end %Define three points in the image; (x,y,z) P = [... @@ -6730,9 +6853,10 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) global SET NO -if ~orthogonalresamplecheck(NO,[1 0 0],[0 1 0],'transversal'); + +if ~orthogonalresamplecheck(NO,[1 0 0],[0 1 0],'transversal') return; -end; +end %Define three points in the image; (x,y,z) P = [... @@ -6755,13 +6879,13 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) %------------------------------ %Crop intensities above and under HU threshold -global SET NO +global DATA SET NO no = NO; if ~isequal(SET(no).Modality,'CT') myfailed('Only CT are supported.'); return; -end; +end %Ask for values s = []; @@ -6792,11 +6916,137 @@ function orthogonalresamplehelper(no,P,flipv,pos,newdimorder) SET(no).IntensityScaling = SET(no).IntensityScaling/(maxim-minim); SET(no).IntensityScaling = SET(no).IntensityScaling/(maxim-minim); SET(no).IntensityOffset = s.MinHU; - -end; +end %Update graphically sliderupdated = false; calculatepreview = true; drawfunctions('drawthumbnails',calculatepreview,sliderupdated); -drawfunctions('drawcontrastimage',no); +DATA.ViewIM{DATA.CurrentPanel} = []; +drawfunctions('drawimages',DATA.CurrentPanel); + +%---------------- +function smartepi +%---------------- +%Tool for smart epi segmentation from endo ballon tool +%activates by 'space' when you have current tool EndoBalloon + +global SET NO + +segmentation('epicopyfromlvendo_Callback'); %copy segmentation from endo to epi and expand 5mm +if ~isempty(SET(NO).StrainTagging) && isfield(SET(NO).StrainTagging, 'LVupdated') + SET(NO).StrainTagging.LVupdated = 1; +end +calcfunctions('updatemarandscar',no); + +%---------------- +function closeallongoinginterpolations %#ok used in filemenu.m +%---------------- +global SET + +%go over all stacks and close all ongoing interpolations +for noloop = 1:length(SET) + connectinterpolation(noloop,{'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}) +end + +%--------------------------------- +function connectinterpolation(no,typestoconnect) +%--------------------------------- +% function to close interpolation line +global DATA SET +interptypes = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; +if nargin == 1 + iconnames = {'interpendo','interpepi','interprvendo','interprvepi'}; + numicons = length(iconnames); + iconstate = zeros(1,numicons); + for loop = 1:numicons + iconstate(loop) = DATA.Handles.configiconholder.findindented(iconnames{loop}); + end + ind = find(iconstate); +else + interptypes = interptypes(ismember(interptypes,typestoconnect)); + ind = []; + for typeloop = 1:length(interptypes) + type = interptypes{typeloop}; + if SET(no).([type(1:end-6),'InterpOngoing']) + ind = [ind,typeloop]; %#ok + end + end +end + +panels = find(DATA.ViewPanels == no); + +if ~isempty(ind) + for loop = 1:length(ind) + type = interptypes{ind(loop)}; + resetinterpolation(no,{type}) + datax = SET(no).([type,'X']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice}; + datay = SET(no).([type,'Y']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice}; + if length(datax) > 2 + valueind = ~isnan(datax); + datax = datax(valueind); + datay = datay(valueind); + + %get rid of Nans if any exist + [x,y] = calcfunctions('resamplecurve',datax,datay,DATA.NumPoints-1); + + newx = [x,x(1)]'; + newy = [y,y(1)]'; + if DATA.ThisFrameOnly + SET(no).([type(1:end-6),'X'])(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)= newx; + SET(no).([type(1:end-6),'Y'])(:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice)= [y,y(1)]; + else + % duplicate new contours to all time frames + SET(no).([type(1:end-6),'X'])(:,:,SET(no).CurrentSlice)= repmat(newx,1,SET(no).TSize,1); + SET(no).([type(1:end-6),'Y'])(:,:,SET(no).CurrentSlice)= repmat(newy,1,SET(no).TSize,1); + end + + else + SET(no).([type,'X']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + SET(no).([type,'Y']){SET(no).CurrentTimeFrame,SET(no).CurrentSlice} = []; + end + try + for numpanel = 1:length(panels) + resetinterpolationcontours(panels(numpanel),type(1:end-6)) + drawfunctions('drawcontours',panels(numpanel),type(1:end-6)) + if length(datax) < 3 + DATA.Handles.([lower(type(1:end-6)),'contour'])(panels(numpanel)).XData = nan; + DATA.Handles.([lower(type(1:end-6)),'contour'])(panels(numpanel)).YData = nan; + end + end + catch me + mydispexception(me) + end + end +end +segment('updatevolume'); + +%--------------------------------- +function resetinterpolation(no,interptypes) +%--------------------------------- +global SET +if nargin == 1 + interptypes = {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}; +end + +for loop = 1:length(interptypes) + type = interptypes{loop}; + SET(no).([type(1:end-6),'InterpOngoing']) = false; +end + +%--------------------------------- +function resetinterpolationcontours(panel,interptypes) +%--------------------------------- +global DATA +if nargin == 1 + interptypes = {'Endo','Epi','RVEndo','RVEpi'}; +else + interptypes = {interptypes}; +end + +for loop = 1:length(interptypes) + type = interptypes{loop}; + DATA.Handles.([lower(type),'contour'])(panel).LineStyle = '-'; + DATA.Handles.([lower(type),'contour'])(panel).Marker = 'none'; +end + diff --git a/source/trackit.mexw32 b/source/trackit.mexw32 deleted file mode 100644 index 9ef9b39..0000000 Binary files a/source/trackit.mexw32 and /dev/null differ diff --git a/source/trackit_helper.mexw32 b/source/trackit_helper.mexw32 deleted file mode 100644 index e837f35..0000000 Binary files a/source/trackit_helper.mexw32 and /dev/null differ diff --git a/source/transittimetool.m b/source/transittimetool.m index d4303d9..b369b10 100644 --- a/source/transittimetool.m +++ b/source/transittimetool.m @@ -16,7 +16,7 @@ if SET(NO).RoiN<2 myfailed('Need 2 ROIs for transit time calculations.',DATA.GUI.Segment); return; -end; +end tempnos=NO; imissingle=classcheckim(tempnos);%checks so that SET(tempnos).IM is single and can also convert from int16 to singel if user wants @@ -28,11 +28,11 @@ if isempty(SET(NO).EndAnalysis) SET(NO).EndAnalysis = SET(NO).TSize; -end; +end if isempty(SET(NO).StartAnalysis) SET(NO).StartAnalysis = 1; -end; +end %if (SET(NO).EndAnalysis-SET(NO).StartAnalysis)<1 % myfailed('No timespan, adjust Start/End analysis time (under stress menu or drag red bar).',DATA.GUI.Segment); @@ -88,8 +88,8 @@ f = exp(-x.^2/gui.sigma.^2); figure(22); plot(x,f); -xlabel('Timeframes'); -title('Smoothing applicability.'); +xlabel(dprintf('Timeframes')); +title(dprintf('Smoothing applicability.')); %-------------- function recalc @@ -119,7 +119,7 @@ temp = SET(gui.no).IM(:,:,tloop,z); else temp = calcfunctions('calctruedata',SET(gui.no).IM(:,:,tloop,z),gui.no); - end; + end roimask = segment('createmask',... [SET(gui.no).XSize SET(gui.no).YSize],... SET(gui.no).Roi(gui.rois(rloop)).Y(:,tloop),... @@ -130,15 +130,15 @@ gui.roimax(tloop,rloop) = max(temp(ind)); gui.roiint(tloop,rloop) = mean(temp(ind)); gui.roistd(tloop,rloop) = std(temp(ind)); - end; + end gui.roisize(tloop,rloop) = (1/100)*stablepolyarea(... SET(gui.no).ResolutionY*SET(gui.no).Roi(gui.rois(rloop)).Y(:,tloop),... SET(gui.no).ResolutionX*SET(gui.no).Roi(gui.rois(rloop)).X(:,tloop)); gui.roisizepix(tloop,rloop) = sum(roimask(:))*SET(gui.no).ResolutionX*SET(gui.no).ResolutionY/100; h = mywaitbarupdate(h); - end; - end; -end; + end + end +end mywaitbarclose(h); doplot; set(gui.fig,'Pointer','Arrow'); @@ -174,7 +174,7 @@ myfailed('Not yet implemented.',DATA.GUI.Segment); gui.outdata = []; gui.outname = ''; -end; +end bl1 = str2double(get(gui.handles.inbaseedit,'String')); if ~isnan(bl1) @@ -203,7 +203,7 @@ detrend = detrend(:); %reshape detrend = repmat(detrend,[1 size(gui.outdata,2)]); %reshape gui.outdata = gui.outdata-detrend; -end; +end %--- Do smoothing @@ -221,11 +221,11 @@ temp = gui.outdata(:,rloop); temp = conv2(temp,f','same')./(eps+conv2(ones(size(temp)),f','same')); gui.smoothoutdata(:,rloop) = temp; - end; + end else gui.smoothoutdata = gui.outdata; gui.t = SET(gui.no).TimeVector; -end; +end basecheckbox = [gui.handles.inbasecheckbox gui.handles.outbasecheckbox]; @@ -287,7 +287,7 @@ else gui.fwhmstart(rloop) = pos(1); gui.fwhmend(rloop) = pos(end); - end; + end %Centerofgravity temp = gui.smoothoutdata(gui.limits(rloop,1):gui.limits(rloop,2),rloop); @@ -303,7 +303,7 @@ gui.centergravity(rloop) = temp_nom/temp_den; else gui.centergravity(rloop) = NaN; - end; + end %Plot max/min if get(gui.handles.showminmaxcheckbox,'value') @@ -311,7 +311,7 @@ plot(handles(rloop),gui.t(gui.maxind(rloop)),gui.maxv(rloop),'k*'); plot(handles(rloop),[gui.t(1) gui.t(end)],[gui.minv(rloop) gui.minv(rloop)],'k:'); plot(handles(rloop),[gui.t(1) gui.t(end)],[gui.maxv(rloop) gui.maxv(rloop)],'k:'); - end; + end %Plot min/max slopes if get(gui.handles.showslopescheckbox,'value') @@ -332,7 +332,7 @@ right = temp(gui.maxindd(rloop))+gui.maxvd(rloop)*deltat; plot(handles(rloop),gui.t(gui.maxindd(rloop))+[-deltat deltat],[left right],'k-'); plot(handles(rloop),[gui.t(gui.maxindd(rloop)) gui.t(gui.maxindd(rloop))],ylim,'k:'); - end; + end %Plot FWHM if get(gui.handles.showfwhmcheckbox,'value')&&~isnan(gui.fwhmstart(rloop)) @@ -340,7 +340,7 @@ plot(handles(rloop),[gui.t(1) gui.t(end)],[gui.fwhm(rloop) gui.fwhm(rloop)],'k:'); plot(handles(rloop),[gui.t(gui.fwhmstart(rloop)) gui.t(gui.fwhmstart(rloop))],ylim,'k:'); plot(handles(rloop),[gui.t(gui.fwhmend(rloop)) gui.t(gui.fwhmend(rloop))],ylim,'k:'); - end; + end %Plot CenterGravity @@ -349,9 +349,9 @@ if get(gui.handles.showcentergravitycheckbox,'value') ylim = get(handles(rloop),'ylim'); plot(handles(rloop),centergravityt*[1 1],ylim,'k:'); - end; + end - end; %rloop + end %rloop onradiobuttons = [... gui.handles.onminradiobutton ... @@ -376,7 +376,7 @@ % set(h,'linewidth',2); % % end; - end; + end %Add baseline crop if mygetvalue(gui.handles.inbasecheckbox) @@ -418,10 +418,10 @@ legend(gui.handles.inflowaxes,legendstring{1}); legend(gui.handles.outflowaxes,legendstring{2}); - xlabel(gui.handles.inflowaxes,'Time [s]'); - ylabel(gui.handles.inflowaxes,'Signal Intensity [a.u.]'); - xlabel(gui.handles.outflowaxes,'Time [s]'); - ylabel(gui.handles.outflowaxes,'Signal Intensity [a.u.]'); + xlabel(gui.handles.inflowaxes,dprintf('Time [s]')); + ylabel(gui.handles.inflowaxes,dprintf('Signal Intensity [a.u.]')); + xlabel(gui.handles.outflowaxes,dprintf('Time [s]')); + ylabel(gui.handles.outflowaxes,dprintf('Signal Intensity [a.u.]')); yticks = get(gui.handles.inflowaxes,'YTick'); yticksspaced = yticks(1):0.01:yticks(end); @@ -444,7 +444,7 @@ bar(gui.handles.inflowaxes,gui.outdata(gui.rois)'); %set(gui.handles.inflowaxes,'xticklabel',legendstring); -end; +end %------------------------------------ function baseline_Buttondown(inorout) @@ -539,14 +539,14 @@ function roibar_Buttonup(type,inorout) %#ok gui.limits(2,1) = x; case 'offset-endbar' gui.limits(2,2) = x; -end; +end for rloop = 1:2 if gui.limits(rloop,1) > gui.limits(rloop,2) temp = gui.limits(rloop,1); gui.limits(rloop,1)=gui.limits(rloop,2); gui.limits(rloop,2)=temp; - end; + end end %------------------ @@ -559,7 +559,7 @@ function roibar_Buttonup(type,inorout) %#ok n = str2double(s); if not(isnan(n)) gui.sigma = n; -end; +end gui.sigma = min(max(gui.sigma,get(gui.handles.smoothslider,'min')),get(gui.handles.smoothslider,'max')); set(gui.handles.sigmaedit,'string',sprintf('%0.5g',gui.sigma)); set(gui.handles.smoothslider,'value',gui.sigma); @@ -615,12 +615,12 @@ function roibar_Buttonup(type,inorout) %#ok c{16,2} = gui.sigma; else c{16,1} = 'No smoothing'; -end; +end if get(gui.handles.cropzerocheckbox,'value') c{17,1} = 'Cropping'; else c{17,1} = 'No cropping'; -end; +end for rloop=1:length(gui.rois) c{3,2+(rloop-1)*2} = SET(gui.no).Roi(gui.rois(rloop)).Name; c{4,2+(rloop-1)*2} = 'Value'; @@ -647,7 +647,7 @@ function roibar_Buttonup(type,inorout) %#ok c{13,3+(rloop-1)*2} = gui.t(gui.fwhmend(rloop)); c{14,3+(rloop-1)*2} = (gui.centergravity(rloop)-1)*SET(gui.no).TIncr; -end; +end segment('cell2clipboard',c); %---------------------- diff --git a/source/txmap.p b/source/txmap.p index daabde3..47e95bd 100644 Binary files a/source/txmap.p and b/source/txmap.p differ diff --git a/source/updatetool.m b/source/updatetool.m deleted file mode 100644 index a42af34..0000000 --- a/source/updatetool.m +++ /dev/null @@ -1,1332 +0,0 @@ -function updatetool(newtype,panel,skiptfo) -%Update display of tools and also callbacks of the graphical objects in -%the panel. If panel given then only update the panel, otherwise all image -%panels are updated. - -global DATA SET - -persistent stamp - -if ~DATA.Testing - %This section avoids double click and avoids problems with space triggering - %twice - if isempty(stamp) - stamp = now; - end; - - deltat = (now-stamp)*24*3600; - stamp = now; - - %Check if clicked very recently - if (deltat>0) && (deltat<0.1) - return; - end; -end - -if DATA.Silent - return; -end; -if nargin < 3 - skiptfo = false; -end -if nargin>0 - if isequal(DATA.CurrentTool,newtype) - skiptfo = true; %Skip changing of this frame only mode - end - if isempty(SET) - return - end; -else - newtype = DATA.CurrentTool; - skiptfo = true; -end; - -%This fixes so that when calling drawall -if strcmp(DATA.CurrentTheme,'3dp') - %DATA.Handles.configiconholder.indent(DATA.CurrentTool,1) - %set the button down for all panels - numpanels = numel(DATA.ViewPanels); - for i = 1:numpanels - switch DATA.ViewPanelsType{i} - case 'trans3DP' - set(DATA.Handles.imagehandle(i),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''r'')'); - case 'sag3DP' - set(DATA.Handles.imagehandle(i),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''g'')'); - case 'cor3DP' - set(DATA.Handles.imagehandle(i),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''b'')'); - case 'speedim' - set(DATA.Handles.imagehandle(i),'ButtonDownFcn','segment3dp.tools(''click3dp_Callback'',''s'')'); - end - end - return -end - -if isempty(newtype) - newtype = 'select'; -end; - -%Select slices tool becomes orthoview tool if orthogonal view is present -if strcmp(newtype,'select') && numel(DATA.ViewPanelsType) >= 3 && ... - isequal(DATA.ViewPanelsType{1},'ortho') - newtype = 'orthoview'; -end - -if strcmp(newtype,'orthoview') - indent(DATA.Handles.configiconholder,'select',0) %select is always there -end - -oldtype = DATA.CurrentTool; -DATA.CurrentTool = newtype; - -%Reset mouse button functions -set(DATA.imagefig,'WindowButtonDownFcn',''); -%set(DATA.imagefig,'WindowButtonMotionFcn',''); - -if length(SET)<1 - return; -end; - -%If no mode selected then set LV as default -if isempty(DATA.Tools) - %DATA.CurrentTheme='lv'; - %DATA.updateicons('lv'); -end; - -%Loop only over active panels -if nargin>1 && ~isempty(panel) - panelstodo = panel; -else - panelstodo = 1:length(DATA.ViewPanels); -end; - - -%Set this frame only mode depending on new tool -autolist = {'autolv', 'autoendo', 'autoepi', 'autorvendo', 'autolvct', ... - 'trackroi', 'autoscar', 'automar', 'autocropall','ctlvreconstruct','autorvct'}; -asklist = {'autolv','autolvct','autorvct'}; -%if strcmp(DATA.ProgramName,'SegmentCMR') - notthisframeonlylist = {'trackroi','drawroi','putroi'}; %WAS: setdiff(autolist,'autoscar'); - % thisframeonlylist = {'drawendo','drawepi','drawrvendo','drawrvepi',... - % 'drawroi','drawscar','drawmo','drawrubber','drawrubberpen',... - % 'drawmarpen','drawmarrubberpen','drawmarrubber','putroi','interpendo',... - % 'interpepi','interprvendo','interprvepi'}; - thisframeonlylist = {'drawendo','drawepi','drawrvendo','drawrvepi',... - 'drawscar','drawmo','drawrubber','drawrubberpen',... - 'drawmarpen','drawmarrubberpen','drawmarrubber','interpendo',... - 'interpepi','interprvendo','interprvepi'}; - derivedlaxlist = {'orthoview','select','move','moveall','contrast','click3d','measure'}; -%end -if isempty(setdiff({oldtype,newtype},thisframeonlylist)) || ... - isempty(setdiff({oldtype,newtype},notthisframeonlylist)) - skiptfo = true; -end -silent = false; -no = DATA.ViewPanels(DATA.CurrentPanel); -% if ~skiptfo -% switch newtype -% case notthisframeonlylist -% if DATA.ThisFrameOnly -% DATA.thisframeonly_Callback(false,silent); -% end -% case thisframeonlylist -% if ~DATA.ThisFrameOnly && ~any(cellfun(@numel,{SET.EchoTime}) > 1) -% DATA.thisframeonly_Callback(true,silent); -% end -% case asklist -% if DATA.ThisFrameOnly && SET(no).TSize > 1 -% % if yesno(['Currently in Single Frame Mode. ' ... -% % 'Change to do all timeframes?']) -% DATA.thisframeonly_Callback(false,silent); -% % end -% end -% end -% end - -if ~ismember(newtype, derivedlaxlist) - %Do not set callbacks for HLA/VLA/GLA images unless type is in this list - panelstodo = panelstodo(~ismember(DATA.ViewPanelsType(panelstodo),{'hla','vla','gla'})); -end - -%Take care of automatic segmentation methods -if ismember(newtype, autolist) - %Warn if dangerous image size -% if ismember(newtype, {'autorvendo'}) -% automaxsz = 256*200; -% if SET(no).XSize*SET(no).YSize > 2*automaxsz -% if ~yesno(['Warning: Auto segmentation of an image this size might ' ... -% 'cause fatal memory errors. We strongly recommend that you '... -% 'crop the image before auto segmenting. Proceed anyway?']); -% return -% end -% end -% end - - %DATA.CurrentTool = 'select'; -DATA.CurrentTool = oldtype; - - switch newtype - case 'autolv' - lvsegmentation;%lv('segmentfullyautomatic_Callback'); - case 'autoendo' - lvpeter('segmentendo_Callback'); - case 'autoepi' - lvpeter('segmentepi_Callback'); - case 'autorvendo' - rvsegmentation; %rv('segmentrvendo_Callback'); - case 'autolvct' - ct.ctlicensecheck('CTLVSegmentation'); - case 'autorvct' - ct.ctlicensecheck('CTRVSegmentation'); - case 'ctlvreconstruct' - ct.imagestacksct; - case 'trackroi' - flow('flowtrackroi_Callback'); - case 'autoscar' - viability('viabilityautoewa'); - case 'automar' - mar('auto_Callback'); - case 'autocropall' - ask = true; - autocropall(ask); - end -end - -%suspect graphics occasionally hindering tool update this should fix it -drawnow -pause(0.05) - -%Set callbacks and highlight tool for all panels -for loop=panelstodo - if DATA.ViewPanels(loop)>0 - - panel = loop; - if strcmp(newtype,'orthoview') && ... - ~ismember(DATA.ViewPanelsType{panel},{'ortho','hla','vla','gla'}) - newtype = 'select'; - end - %use remove nan is not properly initiated. - myset([DATA.Handles.endointerp(panel)... - DATA.Handles.epiinterp(panel)... - DATA.Handles.rvendointerp(panel)... - DATA.Handles.rvepiinterp(panel)],... - 'ButtonDownFcn',[]); - %Check the new tool and update accordingly - switch newtype - case 'point' -% if isfield(DATA.Tools,'point') -% segment('highlighttool',DATA.Tools.point); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel}],'ButtonDownFcn',... - sprintf('%s(''point_Buttondown'',%d)','segment',panel)); - myset([... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel}],'ButtonDownFcn',... - sprintf('%s(''pointat_Buttondown'',%d)','annotationpoint',panel)); - load('pointers.mat'); - myset(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.point,... - 'pointershapehotspot',[7 7]); - %set(DATA.fig,'pointer','cross'); - - case 'measure' -% if isfield(DATA.Tools,'measure') -% segment('highlighttool',DATA.Tools.measure); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel}],'ButtonDownFcn',... - sprintf('%s(''measure_Buttondown'',%d)','segment',panel)); - myset([... - DATA.Handles.measureline{panel}{1:numel(SET(DATA.ViewPanels(panel)).Measure)} ... - DATA.Handles.measuretext{panel}(1:numel(SET(DATA.ViewPanels(panel)).Measure))], ... - 'ButtondownFcn',... - sprintf('%s(''measurepoint_Buttondown'',%d)','segment',panel)); - if isa(DATA.GUISettings.MeasurePointer, 'string')||isa(DATA.GUISettings.MeasurePointer, 'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.MeasurePointer); - else - set(DATA.imagefig,'pointer','custom',... - 'PointerShapeCData',DATA.GUISettings.MeasurePointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.MeasurePointer.hotspot); - end - - case 'click3d' -% if isfield(DATA.Tools,'click3d') -% segment('highlighttool',DATA.Tools.click3d); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel}],'ButtonDownFcn',... - sprintf('longaxistools(''showpointinallviews'',%d)',loop)); - set(DATA.imagefig,'pointer','arrow'); - - case 'orthoview' - %segment('highlighttool',DATA.Tools.selectslices); - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel}],'ButtonDownFcn',... - sprintf('segment(''orthoview_Buttondown'',%d)',loop)); - - - case 'select' - %Slice selecttools - %segment('highlighttool',DATA.Tools.selectslices); - - %Set up vector of handles - h = [... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel}]; - if ismember(DATA.ViewPanelsType{panel},{'montage','montagerow','montagefit','sax3','montagesegmented'}) - myset(h,'ButtonDownFcn',... - sprintf('%s(''montage_Buttondown'',%d)','segment',panel)); - for roiloop = 1:numel(DATA.Handles.roicontour{panel}) - myset(... - DATA.Handles.roicontour{panel}(roiloop), 'ButtonDownFcn', ... - sprintf('%s(''selectroi_Buttondown'',%d,%d)','roi',panel,roiloop)); - end - pause(0.05); %Sometimes does not get set properly without pause - else -% drawnow -% pause(0.05) - myset(h,'ButtonDownFcn',... - sprintf('%s(''normal_Buttondown'',%d)','segment',panel)); - for roiloop = 1:numel(DATA.Handles.roicontour{panel}) - myset([... - DATA.Handles.roicontour{panel}(roiloop) ... - DATA.Handles.roitext{panel}(roiloop)], 'ButtonDownFcn', ... - sprintf('%s(''selectroi_Buttondown'',%d,%d)','roi',panel,roiloop)); - end - end; - - myset([... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel}],'ButtondownFcn',... - sprintf('%s(''measurepoint_Buttondown'',%d)','segment',panel)); - myset([... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel}],'ButtonDownFcn',... - sprintf('%s(''pointat_Buttondown'',%d)','annotationpoint',panel)); - set(DATA.Handles.center{panel},'ButtonDownFcn',... - sprintf('%s(''center_Buttondown'',%d)','segment',panel)); - set(DATA.imagefig,'pointer','arrow'); - - case 'drawendo' -% if isfield(DATA.Tools,'endopen') -% segment('highlighttool',DATA.Tools.endopen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''endo'',1)','segment',panel)); - myset(DATA.Handles.endocontour(panel),'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''endo'',0)','segment',panel)); - if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); - else - set(DATA.imagefig,'pointer','custom',... - 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); - end - case 'drawepi' -% if isfield(DATA.Tools,'epipen') -% segment('highlighttool',DATA.Tools.epipen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''epi'',1)','segment',panel)); - myset(DATA.Handles.epicontour(panel),'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''epi'',0)','segment',panel)); - if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); - else - set(DATA.imagefig,'pointer','custom',... - 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); - end - case 'drawrvendo' -% if isfield(DATA.Tools,'rvendopen') -% segment('highlighttool',DATA.Tools.rvendopen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''rvendo'',1)','segment',panel)); - myset(DATA.Handles.rvendocontour(panel),'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''rvendo'',0)','segment',panel)); - if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); - else - set(DATA.imagefig,'pointer','custom',... - 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); - end - - case 'drawrvepi' -% if isfield(DATA.Tools,'rvepipen') -% segment('highlighttool',DATA.Tools.rvepipen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''rvepi'',1)','segment',panel)); - myset(DATA.Handles.rvepicontour(panel),'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''rvepi'',0)','segment',panel)); - if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); - else - set(DATA.imagefig,'pointer','custom',... - 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); - end - - case 'drawroi' -% if isfield(DATA.Tools,'roipen') -% segment('highlighttool',DATA.Tools.roipen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end -% %Unhide the tool -% stateandicon=segment('iconson','hideroi'); -% stateandicon{2}.isindented=0; -% stateandicon{2}.cdataDisplay=stateandicon{2}.cdata; -% DATA.Handles.configiconholder.render -% feval(stateandicon{2}.execute) - - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''roi'',1)','segment',panel)); - myset([DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel}],'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''roi'',0)','segment',panel)); - - if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); - else - set(DATA.imagefig,'pointer','custom',... - 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); - end - - case 'drawscar' -% if isfield(DATA.Tools,'scarpen') -% segment('highlighttool',DATA.Tools.scarpen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''scar'')','segment',panel)); - if isa(DATA.GUISettings.DrawPointer,'string')||isa(DATA.GUISettings.DrawPointer,'char') - set(DATA.imagefig,'pointer',DATA.GUISettings.DrawPointer); - else - set(DATA.imagefig,'pointer','custom',... - 'pointershapecdata',DATA.GUISettings.DrawPointer.cdata,... - 'pointershapehotspot',DATA.GUISettings.DrawPointer.hotspot); - end - - case 'drawmo' -% if isfield(DATA.Tools,'mopen') -% segment('highlighttool',DATA.Tools.mopen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''mo'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'drawrubber' -% if isfield(DATA.Tools,'rubber') -% segment('highlighttool',DATA.Tools.rubber); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''manualdraw_Buttondown'',%d,''rubber'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'drawrubberpen' -% if isfield(DATA.Tools,'rubberpen') -% segment('highlighttool',DATA.Tools.rubberpen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''rubberpen'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'drawmarpen' -% if isfield(DATA.Tools,'marpen') -% segment('highlighttool',DATA.Tools.marpen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''drawmarpen'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'drawmarrubberpen' -% if isfield(DATA.Tools,'marrubberpen') -% segment('highlighttool',DATA.Tools.marrubberpen); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''drawmarrubberpen'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'drawmarrubber' -% if isfield(DATA.Tools,'marrubber') -% segment('highlighttool',DATA.Tools.marrubber); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',... - sprintf('%s(''manualdraw_Buttondown'',%d,''drawmarrubber'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'endopin' - segment('putpin_Callback',panel,'endo'); %Sets up - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.putpin,... - 'pointershapehotspot',[7 7]); - - case 'epipin' - segment('putpin_Callback',panel,'epi'); %Sets up - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.putpin,... - 'pointershapehotspot',[7 7]); - - case 'rvendopin' - segment('putpin_Callback',panel,'rvendo'); %Sets up - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.putpin,... - 'pointershapehotspot',[7 7]); - - case 'contrast' -% if isfield(DATA.Tools,'contrastbrightness') -% segment('highlighttool',DATA.Tools.contrastbrightness); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - - - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',... - sprintf('segment(''contrast_Callback'',''down'',%d)',panel)); - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.contrast,... - 'pointershapehotspot',[7 7]); - - case 'crop' -% if isfield(DATA.Tools,'crop') -% segment('highlighttool',DATA.Tools.crop); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - ],'ButtonDownFcn',sprintf('tools(''crop_Buttondown'',%d)',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'move' - myset(DATA.Handles.roicontour{panel},'ButtonDownFcn',... - sprintf('segment(''move_Buttondown'',''roi'',%d)',panel)); - myset(DATA.Handles.roitext{panel},'ButtonDownFcn',... - sprintf('segment(''move_Buttondown'',''roi'',%d)',panel)); - myset(DATA.Handles.endocontour(panel),'ButtonDownFcn',... - sprintf('segment(''move_Buttondown'',''endo'',%d)',panel)); - myset(DATA.Handles.epicontour(panel),'ButtonDownFcn',... - sprintf('segment(''move_Buttondown'',''epi'',%d)',panel)); - myset(DATA.Handles.rvendocontour(panel),'ButtonDownFcn',... - sprintf('segment(''move_Buttondown'',''rvendo'',%d)',panel)); - myset(DATA.Handles.rvepicontour(panel),'ButtonDownFcn',.... - sprintf('segment(''move_Buttondown'',''rvepi'',%d)',panel)); - -% myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... -% sprintf('segment(''move_Buttondown'',''image'',%d)',panel)); -myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('segment(''buttondowntoggler'',''move'',%d)',panel)); - -myset([... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel}],'ButtonDownFcn',... - sprintf('%s(''pointat_Buttondown'',%d)','annotationpoint',panel)); - myset([... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel}],'ButtondownFcn',... - sprintf('%s(''measurepoint_Buttondown'',%d)','segment',panel)); - - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.move,... - 'pointershapehotspot',[7 7]); - set(DATA.Handles.center{panel},'ButtonDownFcn',... - sprintf('%s(''center_Buttondown'',%d)','segment',panel)); - %set(DATA.imagefig,'pointer','cross'); - - case 'moveall' - %myset(DATA.Handles.roicontour{panel},'ButtonDownFcn',... - % sprintf('segment(''moveall_Buttondown'',''roi'',%d)',panel)); - %myset(DATA.Handles.roitext{panel},'ButtonDownFcn',... - % sprintf('segment(''moveall_Buttondown'',''roi'',%d)',panel)); - myset(DATA.Handles.endocontour(panel),'ButtonDownFcn',... - sprintf('segment(''moveall_Buttondown'',''endo'',%d)',panel)); - myset(DATA.Handles.epicontour(panel),'ButtonDownFcn',... - sprintf('segment(''moveall_Buttondown'',''epi'',%d)',panel)); - myset(DATA.Handles.rvendocontour(panel),'ButtonDownFcn',... - sprintf('segment(''moveall_Buttondown'',''rvendo'',%d)',panel)); - myset(DATA.Handles.rvepicontour(panel),'ButtonDownFcn',.... - sprintf('segment(''moveall_Buttondown'',''rvepi'',%d)',panel)); - % myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - % sprintf('segment(''moveall_Buttondown'',''image'',%d)',panel)); -% myset([... -% DATA.Handles.pointp{panel} ... -% DATA.Handles.pointo{panel} ... -% DATA.Handles.pointtext{panel}],'ButtonDownFcn',... -% sprintf('%s(''pointat_Buttondown'',%d)','annotationpoint',panel)); -% myset([... -% DATA.Handles.measureline{panel}{:} ... -% DATA.Handles.measuretext{panel}],'ButtondownFcn',... -% sprintf('%s(''measurepoint_Buttondown'',%d)','segment',panel)); -% - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.move,... - 'pointershapehotspot',[7 7]); - set(DATA.Handles.center{panel},'ButtonDownFcn',... - sprintf('%s(''center_Buttondown'',%d)','segment',panel)); - case 'scaleROI' - myset(DATA.Handles.roicontour{panel},'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''roi'',%d)',panel)); - myset(DATA.Handles.roitext{panel},'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''roi'',%d)',panel)); - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.scale,... - 'pointershapehotspot',[7 7]); - set(DATA.Handles.center{panel},'ButtonDownFcn',... - sprintf('%s(''center_Buttondown'',%d)','segment',panel)); - - case 'scale' -% if isfield(DATA.Tools,'scale') -% segment('highlighttool',DATA.Tools.scale); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset(DATA.Handles.roicontour{panel},'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''roi'',%d)',panel)); - myset(DATA.Handles.roitext{panel},'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''roi'',%d)',panel)); - myset(DATA.Handles.endocontour(panel),'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''endo'',%d)',panel)); - myset(DATA.Handles.epicontour(panel),'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''epi'',%d)',panel)); - myset(DATA.Handles.rvendocontour(panel),'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''rvendo'',%d)',panel)); - myset(DATA.Handles.rvepicontour(panel),'ButtonDownFcn',... - sprintf('segment(''scale_Buttondown'',''rvepi'',%d)',panel)); - myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('segment(''buttondowntoggler'',''scale'',%d)',panel)); -% myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... -% sprintf('segment(''scale_Buttondown'',''image'',%d)',panel)); - myset([... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel}],'ButtonDownFcn',... - sprintf('%s(''pointat_Buttondown'',%d)','annotationpoint',panel)); - myset([... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel}],'ButtondownFcn',... - sprintf('%s(''measurepoint_Buttondown'',%d)','segment',panel)); - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.scale,... - 'pointershapehotspot',[7 7]); - set(DATA.Handles.center{panel},'ButtonDownFcn',... - sprintf('%s(''center_Buttondown'',%d)','segment',panel)); - %set(DATA.imagefig,'pointer','cross'); - - case 'dragepi' -% if isfield(DATA.Tools,'dragepi') -% segment('highlighttool',DATA.Tools.dragepi); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - set(DATA.imagefig,'pointer','arrow') - myset(DATA.Handles.epicontour(panel),'ButtonDownFcn',... - sprintf('segment(''dragepi_Buttondown'',''one'',%d)',panel)); - myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('segment(''dragepi_Buttondown'',''image'',%d)',panel)); - - case 'dragepiallslices' -% if isfield(DATA.Tools,'dragepiallslices') -% segment('highlighttool',DATA.Tools.dragepiallslices); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - set(DATA.imagefig,'pointer','arrow') - myset(DATA.Handles.epicontour(panel),'ButtonDownFcn',... - sprintf('segment(''dragepi_Buttondown'',''allslices'',%d)',panel)); - myset(DATA.Handles.imagehandle(panel),'ButtonDownFcn',... - sprintf('segment(''dragepi_Buttondown'',''image'',%d)',panel)); - - case 'putroi' -% if isfield(DATA.Tools,'putroi') -% segment('highlighttool',DATA.Tools.putroi); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end -% -% stateandicon=segment('iconson','hideroi'); -% stateandicon{2}.isindented=0; -% stateandicon{2}.cdataDisplay=stateandicon{2}.cdata; -% DATA.Handles.configiconholder.render -% feval(stateandicon{2}.execute); - - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - ],'ButtonDownFcn',... - sprintf('roi(''roiputroi_Buttondown'',%d)',panel)); - load('pointers.mat'); - set(DATA.imagefig,... - 'pointer','custom',... - 'pointershapecdata',1+pointer.point,... - 'pointershapehotspot',[7 7]); - %set(DATA.imagefig,'pointer','cross'); - - case 'interpendo' -% if isfield(DATA.Tools,'interpendo') -% segment('highlighttool',DATA.Tools.interpendo); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''interpdraw_Buttondown'',%d,''endo'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'interpepi' -% if isfield(DATA.Tools,'interpepi') -% segment('highlighttool',DATA.Tools.interpepi); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''interpdraw_Buttondown'',%d,''epi'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'interprvendo' -% if isfield(DATA.Tools,'interprvendo') -% segment('highlighttool',DATA.Tools.interprvendo); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.endocontour(panel) ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''interpdraw_Buttondown'',%d,''rvendo'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - case 'interprvepi' -% if isfield(DATA.Tools,'interprvepi') -% segment('highlighttool',DATA.Tools.interprvepi); -% else -% segment('highlighttool',DATA.Tools.selectslices); -% end - myset([... - DATA.Handles.imagehandle(panel) ... - DATA.Handles.center{panel} ... - DATA.Handles.endointersectionline{panel} ... - DATA.Handles.endointersectionpoints{panel} ... - DATA.Handles.epiintersection{panel} ... - DATA.Handles.rvendointersection{panel} ... - DATA.Handles.rvepiintersection{panel} ... - DATA.Handles.epicontour(panel) ... - DATA.Handles.rvendocontour(panel) ... - DATA.Handles.rvepicontour(panel) ... - DATA.Handles.roicontour{panel} ... - DATA.Handles.roitext{panel} ... - DATA.Handles.scarcontour{panel} ... - DATA.Handles.weightedscarcontour{panel} ... - DATA.Handles.moextentcontour{panel} ... - DATA.Handles.mocontour{panel} ... - DATA.Handles.marcontour{panel} ... - DATA.Handles.pointp{panel} ... - DATA.Handles.pointo{panel} ... - DATA.Handles.pointtext{panel} ... - DATA.Handles.planeintersectionline{panel} ... - DATA.Handles.measureline{panel}{:} ... - DATA.Handles.measuretext{panel} ... - ],'ButtonDownFcn',sprintf('%s(''interpdraw_Buttondown'',%d,''rvepi'')','segment',panel)); - set(DATA.imagefig,'pointer','cross'); - - - end; - - %copy contour buttondown to interpolation points. - try - myset(DATA.Handles.endointerp(panel),... - 'ButtonDownFcn',get(DATA.Handles.endocontour(panel),'ButtonDownFcn')); - myset(DATA.Handles.epiinterp(panel),... - 'ButtonDownFcn',get(DATA.Handles.epicontour(panel),'ButtonDownFcn')); - myset(DATA.Handles.rvendointerp(panel),... - 'ButtonDownFcn',get(DATA.Handles.rvendocontour(panel),'ButtonDownFcn')); - myset(DATA.Handles.rvepiinterp(panel),... - 'ButtonDownFcn',get(DATA.Handles.rvepicontour(panel),'ButtonDownFcn')); - catch %#ok - end; - - end; %Found a panel that match NO -end; %Loop over panels -func=get(DATA.fig,'WindowButtonMotionFcn'); -if strcmp(func,'') - set(DATA.fig,'WindowButtonMotionFcn',@DATA.toggleplaceholdermotion); -end -%Set keypress functions -set(DATA.imagefig,'keypressfcn',@(fignum,evnt)segment('keypressed',fignum,evnt)); - -%Set buttondown function for overlay images -for hloop = find(ishandle(DATA.Handles.overlayhandle)) - bdfcn = get(DATA.Handles.imagehandle(hloop),'ButtonDownFcn'); - myset(DATA.Handles.overlayhandle(hloop),'ButtonDownFcn',bdfcn); -end diff --git a/source/usegpu.m b/source/usegpu.m new file mode 100644 index 0000000..24535aa --- /dev/null +++ b/source/usegpu.m @@ -0,0 +1,25 @@ +function use = usegpu() +%Checks if to use GPU, displays message while GPU is "warming up". +% +%See also resetgpu() + +%Einar Heiberg + +global DATA + +use = DATA.Pref.GPU.Use; + +if ~use + return; +end + +if isempty(DATA.GPU) || (~DATA.GPU.Hot) + + %Fire it up + DATA.GPU.Hot = true; + h = waitbar(0,'Initalizing GPU engine.'); + temp = gpuArray(single(0)); %#ok + clear temp; + close(h); + +end \ No newline at end of file diff --git a/source/useragreement.p b/source/useragreement.p index a22a232..5ac2746 100644 Binary files a/source/useragreement.p and b/source/useragreement.p differ diff --git a/source/utility.p b/source/utility.p index a5434ed..639e586 100644 Binary files a/source/utility.p and b/source/utility.p differ diff --git a/source/utilityprivate.p b/source/utilityprivate.p index 4bca008..6951a83 100644 Binary files a/source/utilityprivate.p and b/source/utilityprivate.p differ diff --git a/source/versionhello.fig b/source/versionhello.fig index cab56af..dc9c150 100644 Binary files a/source/versionhello.fig and b/source/versionhello.fig differ diff --git a/source/versionhello.m b/source/versionhello.m index ea92fe6..d6858bf 100644 --- a/source/versionhello.m +++ b/source/versionhello.m @@ -3,9 +3,18 @@ function versionhello(fcn, varargin) feval(fcn,varargin{:}) %------------------------ -function init(stri,title) +function init(stri,title) %#ok %------------------------ +global DATA + +if isfield(DATA.Pref,'NoPopUp') + if DATA.Pref.NoPopUp + return + end +end + gui = openfig('versionhello.fig'); +setupicon(gui); handles = guihandles(gui); set(handles.figure1,'Name',title); set(handles.titletext,'String',stri{1}); @@ -14,18 +23,48 @@ function init(stri,title) set(handles.refertext,'enable','off'); set(handles.clinicaltext,'enable','off'); set(handles.howtoreferpushbutton,'enable','off'); - set(handles.getsegmentcmrpushbutton,'enable','off'); - set(handles.getsegmentctpushbutton,'enable','off'); + set(handles.getsegmentcmrpushbuttont,'visible','off'); + set(handles.getsegmentctpushbutton,'visible','off'); + set(handles.getsegment3dppushbutton,'visible','off'); + set(handles.getstrainpushbutton,'visible','off'); + set(handles.segmentcmrtext,'visible','off'); + set(handles.segmentcttext,'visible','off'); + set(handles.segment3dptext,'visible','off'); set(handles.refertext,'visible','off'); set(handles.clinicaltext,'visible','off'); set(handles.howtoreferpushbutton,'visible','off'); - set(handles.getsegmentcmrpushbutton,'visible','off'); - set(handles.getsegmentctpushbutton,'visible','off'); + set(handles.getsegmentcmrpushbuttont,'enable','off'); + set(handles.getsegmentctpushbutton,'enable','off'); + set(handles.getsegment3dppushbutton,'enable','off'); + set(handles.getstrainpushbutton,'enable','off'); else set(handles.refertext,'String',stri{2}); set(handles.clinicaltext,'String',stri{3}); set(handles.infotext,'enable','off'); - set(handles.infotext,'visible','off'); + set(handles.infotext,'visible','off'); + + try + im = imread('segmentcmrimage.png'); + image(im,'Parent',handles.segmentcmraxes); + axis(handles.segmentcmraxes,'equal'); + axis(handles.segmentcmraxes,'off'); + + im = imread('segmentstrainimage.png'); + image(im,'Parent',handles.strainaxes); + axis(handles.strainaxes,'equal'); + axis(handles.strainaxes,'off'); + + im = imread('segmentctimage.png'); + image(im,'Parent',handles.segmentctaxes); + axis(handles.segmentctaxes,'equal'); + axis(handles.segmentctaxes,'off'); + + im = imread('segment3dpimage.png'); + image(im,'Parent',handles.segment3dpaxes); + axis(handles.segment3dpaxes,'equal'); + axis(handles.segment3dpaxes,'off'); + catch %#ok + end end if length(stri{2}) > 200 @@ -40,26 +79,39 @@ function init(stri,title) axis(handles.medvisoaxes,'off'); catch %#ok end +set(gui,'visible','on'); %------------------- -function ok_Callback +function ok_Callback %#ok %------------------- closereq; %--------------------------- -function howtorefer_Callback +function howtorefer_Callback %#ok %--------------------------- mybrowser('http://medviso.com/research/how-to-refer/'); closereq; %------------------------------ -function getsegmentcmr_Callback +function getsegmentcmr_Callback %#ok +%------------------------------ +mybrowser('http://medviso.com/cmr/'); +closereq; + +%------------------------------ +function getsegment3dp_Callback %#ok +%------------------------------ +mybrowser('http://medviso.com/segment-3dprint/'); +closereq; + +%------------------------------ +function getstrain_Callback %#ok %------------------------------ -mybrowser('http://medviso.com/products/cmr/'); +mybrowser('http://medviso.com/strain/'); closereq; %------------------------------ -function getsegmentct_Callback +function getsegmentct_Callback %#ok %------------------------------ -mybrowser('http://medviso.com/products/ct/'); +mybrowser('http://medviso.com/ct/'); closereq; diff --git a/source/vesselsnake_aprioridata.mat b/source/vesselsnake_aprioridata.mat index ca3df7f..3272a07 100644 Binary files a/source/vesselsnake_aprioridata.mat and b/source/vesselsnake_aprioridata.mat differ diff --git a/source/vesselsnake_flowtrackroi.p b/source/vesselsnake_flowtrackroi.p index 42cc258..406864f 100644 Binary files a/source/vesselsnake_flowtrackroi.p and b/source/vesselsnake_flowtrackroi.p differ diff --git a/source/vesselsnake_overview.p b/source/vesselsnake_overview.p index 250da7c..6a08d3c 100644 Binary files a/source/vesselsnake_overview.p and b/source/vesselsnake_overview.p differ diff --git a/source/viability.p b/source/viability.p index be9ac11..1b75530 100644 Binary files a/source/viability.p and b/source/viability.p differ diff --git a/source/viewfunctions.m b/source/viewfunctions.m new file mode 100644 index 0000000..7a800e1 --- /dev/null +++ b/source/viewfunctions.m @@ -0,0 +1,3198 @@ +function [varargout] = viewfunctions(varargin) +% Functions for querying about the view such as slices in panel and +% zoomstate +% Klas +%Invoke subfunction +macro_helper(varargin{:}); %future macro recording use +if (nargout) + [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard +else + feval(varargin{:}); % FEVAL switchyard +end + +%------------------------------------- +function slices = slicesinpanel(panel) +%------------------------------------- +global DATA SET + +no = DATA.ViewPanels(panel); + +if isequal(no,0) + slices = 0; + return +end + +if isempty(DATA.ViewPanelsType{panel}) + DATA.ViewPanelsType{panel} = 'one'; +end +switch DATA.ViewPanelsType{panel} + case 'montagesegmented' + slices = segment_main('getmontagesegmentedslices',no); + case {'montage','montagerow'} + slices = 1:SET(no).ZSize; + case {'one','orth'} + slices = SET(no).CurrentSlice; + case 'gla' + slices = 0; + case 'vla' + slices = SET(no).VLA.slice; + case 'hla' + slices = SET(no).HLA.slice; + otherwise + slices = []; +end + +%------------------------------- +function scale = getscale(panel) +%------------------------------- +%Returns if the panel should be interpolated or not + +global DATA + +if ~DATA.Pref.ViewInterpolated || any(strcmp(DATA.ViewPanelsType{panel},{'montage','montagesegmented','montagerow'})) + scale = 1; +else + scale = 2; +end + +%--------------------------------------- +function updatezoomandaspectratio(panel) +%--------------------------------------- +%Update zoom state + +global DATA SET + +no = DATA.ViewPanels(panel); + +scale = getscale(panel); +if length(DATA.ViewIM)< panel + return +else + %get the xsz and ysz of the images. Overwritten if 3dp view see case below + xsz = size(DATA.ViewIM{panel},1)/scale; + ysz = size(DATA.ViewIM{panel},2)/scale; + + switch DATA.ViewPanelsType{panel} + case {'montage','montagesegmented','montagerow'} + zoomstate = [0.5;ysz-0.5;0.5;xsz-0.5]; + xres = SET(no).ResolutionX; + yres = SET(no).ResolutionY; + case {'one','orth'} + zoomstate = SET(no).NormalZoomState; + xres = SET(no).ResolutionX; + yres = SET(no).ResolutionY; + case 'hla' + xres = SET(no).SliceThickness + SET(no).SliceGap; + yres = SET(no).ResolutionY; + zoomstate = [0.5;ysz-0.5;0.5;xsz-0.5]; + case 'vla' + xres = SET(no).SliceThickness + SET(no).SliceGap; + yres = SET(no).ResolutionX; + zoomstate = [0.5;ysz-0.5;0.5;xsz-0.5]; + case 'gla' + %General longaxis. glaangle = 0 <=> HLA; glaangle = pi/2 <=> VLA + glaangle = SET(no).GLA.angle; + xres = SET(no).SliceThickness + SET(no).SliceGap; + yres = SET(no).ResolutionY*cos(glaangle)+SET(no).ResolutionX*abs(sin(glaangle)); + zoomstate = updateglazoomstate(no,ysz); + case {'trans3DP','sag3DP','cor3DP','speedim'} + switch DATA.ViewPanelsType{panel} + case 'trans3DP' + color = 'r'; + case 'sag3DP' + color = 'g'; + case 'cor3DP' + color = 'b'; + case 'speedim' + color = SET(no).LevelSet.Pen.Color; + end + [xsz,ysz,xres,yres] = segment3dp.tools('viewsizeandres',color,no); + zoomstate = SET(no).LevelSet.View.([upper(color) 'ZoomState']); + end +end +if isempty(zoomstate) + zoomstate = getnewzoomstate(panel,no); +else + % this is the previous zoom state + if ~isempty(SET(no).NormalZoomState) && strcmp(DATA.ViewPanelsType{panel},'one') + zoomstateold = SET(no).NormalZoomState; + xsizeold = zoomstateold(2)-zoomstateold(1); + ysizeold = zoomstateold(4)-zoomstateold(3); + zoomfold = xsizeold/ysizeold; + + %recalculate zoom state without updating SET struct + zoomstatenew = getnewzoomstate(panel,no,false); + xsizenew = zoomstatenew(2)-zoomstatenew(1); + ysizenew = zoomstatenew(4)-zoomstatenew(3); + zoomfnew = xsizenew/ysizenew; + if ~isapproxequal(zoomfnew,zoomfold) + % if the zoom ratio has changed, update to the newest + SET(no).NormalZoomState = zoomstatenew; + zoomstate = zoomstatenew; + end + end +end + +plotboxaspectratio = [ysz/yres xsz/xres 1]; +dataaspectratio = [1/yres 1/xres 1]; + +if ~DATA.Silent + DATA.Handles.imageaxes(panel).DataAspectRatio = dataaspectratio; + DATA.Handles.imageaxes(panel).PlotBoxAspectRatio = plotboxaspectratio; + DATA.Handles.imageaxes(panel).XLim = scale*zoomstate(1:2); + DATA.Handles.imageaxes(panel).YLim = scale*zoomstate(3:4); +end + +%--------------------- +function updatedrawlist(panel,isonlyannotation) +%----------------------- +%this function should be used at the end of a addition of annotation for +%a panel. +%Linked stacks are taken care of within annotationinpanel +do = viewfunctions('annotationinpanel',panel); +if nargin < 2 + isonlyannotation = false; +end +updatedrawlistfcn_helper(panel,do,isonlyannotation) + +%-------------------------------- +function addtodrawlist(panel,fcn) +%-------------------------------- +%Adds fcn to drawlist for panel + +global DATA + +%%only add if not already there, ismember did not work as mix of strings +%%and function handles. +count = 1; +found = false; +drawlist = DATA.drawlist{panel}; +while (count<=length(drawlist)) && ~found + if isequal(drawlist{count},fcn) + found = true; + end + count = count+1; +end + +%add it +if not(found) + DATA.drawlist{panel}{end+1} = fcn; +end + +%-------------------------------------------------------- +function updatedrawlistfcn_helper(panel,do,isonlyannotation) +%-------------------------------------------------------- +global DATA + +%Drawlist is a cell of cells +DATA.drawlist{panel} = {}; + +if nargin < 3 + isonlyannotation = false; +end + +%image are always drawn if not viewport viewpaneltype +if ~strcmp(DATA.ViewPanelsType{panel},'viewport') + if ~isonlyannotation + addtodrawlist(panel,@()drawfunctions('drawimages',panel)); + end +else + addtodrawlist(panel,@()segment3dp.tools('helprender')); +end + +%Centerpoint always drawn if segment +if strcmp(DATA.ProgramName, 'Segment') + addtodrawlist(panel,@()drawfunctions('drawcentercross',panel)); +end + +if do.point3D + addtodrawlist(panel,@()drawfunctions('drawpoint3D',panel)); +end + +switch DATA.ViewPanelsType{panel} + case {'one','orth'} + + %If orth view then we need to draw the orthanglehandle + if strcmp(DATA.ViewPanelsType{panel},'orth') + addtodrawlist(panel,@()drawfunctions('draworthoanglehandle',panel)); + end + + %Contours + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'contour']) + addtodrawlist(panel,@()drawfunctions('drawcontours',panel,types{i})); + end + end + + %Interpolation + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'interp']) + addtodrawlist(panel,@()drawfunctions('drawinterp',panel,[types{i},'Interp'])); + end + end + + if do.measures + addtodrawlist(panel,@()drawfunctions('drawmeasures',panel)); + end + + if do.text + addtodrawlist(panel,@()drawfunctions('drawtext',panel)); + end + + if do.intersections + addtodrawlist(panel,@()drawfunctions('drawintersections',panel)); + end + + drawrois = false; + for c = 'cgymkwrb' + if do.([c,'roi']) + drawrois = true; + break + end + end + if drawrois + addtodrawlist(panel,@()drawfunctions('drawroi',panel)); + end + + if do.point + addtodrawlist(panel,@()drawfunctions('drawpoint',panel)); + end + + if do.scar + addtodrawlist(panel,@()drawfunctions('drawviability',panel)); + else + do.manualinteraction = 0; + %DATA.ViewIM{panel} = []; + end + + if do.manualinteraction + addtodrawlist(panel,@()drawfunctions('showviabilityedits',panel)); + else + %DATA.ViewIM{panel} = []; + end + + if do.mar + addtodrawlist(panel,@()drawfunctions('drawmar',panel)); + end + + case {'montage','montagerow','montagesegmented'} + + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'contour']) + addtodrawlist(panel,@()drawfunctions('drawcontours',panel,types{i})); + end + end + + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'interp']) + addtodrawlist(panel,@()drawfunctions('drawinterp',panel,[types{i},'Interp'])); + end + end + + if do.measures + addtodrawlist(panel,@()drawfunctions('drawmeasures',panel)); + end + + if do.text + addtodrawlist(panel,@()drawfunctions('drawtext',panel)); + end + + for c = 'cgymkwrb' + if do.([c,'roi']) + addtodrawlist(panel,@()drawfunctions('drawroi',panel,c)); + end + end + + if do.point + addtodrawlist(panel,@()drawfunctions('drawpoint',panel)); + end + + if do.scar + addtodrawlist(panel,@()drawfunctions('drawviability',panel)); + else + do.manualinteraction = 0; + DATA.ViewIM{panel} = []; + end + + if do.manualinteraction + addtodrawlist(panel,@()drawfunctions('showviabilityedits',panel)); + else + DATA.ViewIM{panel} = []; + end + + if do.mar + addtodrawlist(panel,@()drawfunctions('drawmar',panel)); + end + case {'hla','gla','vla'} + if do.text + addtodrawlist(panel,@()drawfunctions('drawtext',panel)); + end + + if do.measures + addtodrawlist(panel,@()drawfunctions('drawmeasures',panel)); + end + + if do.intersections + addtodrawlist(panel,@()drawfunctions('drawintersections',panel)); + end + case {'trans3DP','sag3DP','cor3DP','speedim'} + + types = {'gb','bg','gr','br','rb','rg'}; + for i = 1:length(types) + if do.([types{i} 'line']) + addtodrawlist(panel,@()drawfunctions('draw3dpline',panel,types{i})); + end + end + + %types = {'r','b','g','s'}; + %for i = 1:length(types) + % if do.([types{i} 'contour']) + % DATA.drawlist{panel}{end+1} = @()drawfunctions(''draw3dpoutline'',%d,''%s'')',panel,types{i}); + % end + %end + if do.threedpcontour + addtodrawlist(panel,@()drawfunctions('draw3dpoutline',panel,'threedp')); + end + + if do.point + addtodrawlist(panel,@()drawfunctions('drawpoint',panel)); + end + +end +%-------------------------------------------------------- +function updatedrawlist_helper(panel,do,isonlyannotation) +%-------------------------------------------------------- +global DATA + +%Drawlist is a cell of cells +DATA.drawlist{panel} = {}; + +if nargin < 3 + isonlyannotation = false; +end + +%image are always drawn if not viewport viewpaneltype +if ~strcmp(DATA.ViewPanelsType{panel},'viewport') + if ~isonlyannotation + addtodrawlist(panel,sprintf('drawfunctions(''drawimages'',%d)',panel)); + end +else + addtodrawlist(panel,sprintf('segment3dp.tools(''helprender'');')); +end + +%Centerpoint always drawn if segment +if strcmp(DATA.ProgramName, 'Segment') + addtodrawlist(panel,sprintf('drawfunctions(''drawcentercross'',%d)',panel)); +end + +if do.point3D + addtodrawlist(panel,sprintf('drawfunctions(''drawpoint3D'',%d)',panel)); +end + +switch DATA.ViewPanelsType{panel} + case {'one','orth'} + + %If orth view then we need to draw the orthanglehandle + if strcmp(DATA.ViewPanelsType{panel},'orth') + addtodrawlist(panel,sprintf('drawfunctions(''draworthoanglehandle'',%d)',panel)); + end + + %Contours + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'contour']) + addtodrawlist(panel,sprintf('drawfunctions(''drawcontours'',%d,''%s'')',panel,types{i})); + end + end + + %Interpolation + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'interp']) + addtodrawlist(panel,sprintf('drawfunctions(''drawinterp'',%d,''%s'')',panel,[types{i},'Interp'])); + end + end + + if do.measures + addtodrawlist(panel,sprintf('drawfunctions(''drawmeasures'',%d)',panel)); + end + + if do.text + addtodrawlist(panel,sprintf('drawfunctions(''drawtext'',%d)',panel)); + end + + if do.intersections + addtodrawlist(panel,sprintf('drawfunctions(''drawintersections'',%d)',panel)); + end + +% for c = 'cgymkwrb' +% if do.([c,'roi']) +% DATA.drawlist{panel}{end+1} = sprintf('drawfunctions(''drawroi'',%d,''%s'')',panel,c); +% end +% end + drawrois = false; + for c = 'cgymkwrb' + if do.([c,'roi']) + drawrois = true; + break + end + end + if drawrois + addtodrawlist(panel,sprintf('drawfunctions(''drawroi'',%d)',panel)); + end + + if do.point + addtodrawlist(panel,sprintf('drawfunctions(''drawpoint'',%d)',panel)); + end + + if do.scar + addtodrawlist(panel,sprintf('drawfunctions(''drawviability'',%d)',panel)); + else + do.manualinteraction = 0; + %DATA.ViewIM{panel} = []; + end + + if do.manualinteraction + addtodrawlist(panel,sprintf('drawfunctions(''showviabilityedits'',%d)',panel)); + else + %DATA.ViewIM{panel} = []; + end + + if do.mar + addtodrawlist(panel,sprintf('drawfunctions(''drawmar'',%d)',panel)); + end + + case {'montage','montagerow','montagesegmented'} + + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'contour']) + addtodrawlist(panel,sprintf('drawfunctions(''drawcontours'',%d,''%s'')',panel,types{i})); + end + end + + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + for i = 1:length(types) + if do.([lower(types{i}),'interp']) + addtodrawlist(panel,sprintf('drawfunctions(''drawinterp'',%d,''%s'')',panel,[types{i},'Interp'])); + end + end + + if do.measures + addtodrawlist(panel,sprintf('drawfunctions(''drawmeasures'',%d)',panel)); + end + + if do.text + addtodrawlist(panel,sprintf('drawfunctions(''drawtext'',%d)',panel)); + end + + for c = 'cgymkwrb' + if do.([c,'roi']) + addtodrawlist(panel,sprintf('drawfunctions(''drawroi'',%d,''%s'')',panel,c)); + end + end + + if do.point + addtodrawlist(panel,sprintf('drawfunctions(''drawpoint'',%d)',panel)); + end + + if do.scar + addtodrawlist(panel,sprintf('drawfunctions(''drawviability'',%d)',panel)); + else + do.manualinteraction = 0; + DATA.ViewIM{panel} = []; + end + + if do.manualinteraction + addtodrawlist(panel,sprintf('drawfunctions(''showviabilityedits'',%d)',panel)); + else + DATA.ViewIM{panel} = []; + end + + if do.mar + addtodrawlist(panel,sprintf('drawfunctions(''drawmar'',%d)',panel)); + end + case {'hla','gla','vla'} + if do.text + addtodrawlist(panel,sprintf('drawfunctions(''drawtext'',%d)',panel)); + end + + if do.measures + addtodrawlist(panel,sprintf('drawfunctions(''drawmeasures'',%d)',panel)); + end + + if do.intersections + addtodrawlist(panel,sprintf('drawfunctions(''drawintersections'',%d)',panel)); + end + case {'trans3DP','sag3DP','cor3DP','speedim'} + + types = {'gb','bg','gr','br','rb','rg'}; + for i = 1:length(types) + if do.([types{i} 'line']) + addtodrawlist(panel,sprintf('drawfunctions(''draw3dpline'',%d,''%s'')',panel,types{i})); + end + end + + %types = {'r','b','g','s'}; + %for i = 1:length(types) + % if do.([types{i} 'contour']) + % DATA.drawlist{panel}{end+1} = sprintf('drawfunctions(''draw3dpoutline'',%d,''%s'')',panel,types{i}); + % end + %end + if do.threedpcontour + addtodrawlist(panel,sprintf('drawfunctions(''draw3dpoutline'',%d,''threedp'')',panel)); + end + + if do.point + addtodrawlist(panel,sprintf('drawfunctions(''drawpoint'',%d)',panel)); + end + +end + +%--------------------------------------------------------- +function do = annotationinpanel(panel) %#ok +%----------------------------------------------------------- +%this function sets graphics objects to nan in panel if there is no +%occurence in that slice of the annotation pertaining to that object. +%Returns struct with booleans indicating occurence of annotation. +global DATA SET + +%this is done on panel level so if no segmentatio found in panel then it is +%not displayed in that panel; +slices = viewfunctions('slicesinpanel',panel); +no = DATA.ViewPanels(panel); + +%Assume all exists then turn off later in code. These fields are all +%lowercase and contours have the field name which matches the SET field +%name but lower case and contour after. +do.endocontour = 1; +do.epicontour = 1; +do.rvendocontour = 1; +do.rvepicontour = 1; +do.generalpencontour = 1; +do.endointerp = 1; +do.epiinterp = 1; +do.rvendointerp = 1; +do.rvepiinterp = 1; +do.generalpeninterp = 1; +do.measures = 1; +do.point = 1; +do.point3D = 1; +do.croi = 1; +do.yroi = 1; +do.mroi = 1; +do.kroi = 1; +do.groi = 1; +do.rroi = 1; +do.broi = 1; +do.wroi = 1; +do.text = 1; +do.intersections = 1; +do.scar = 1; +do.mar = 1; +do.manualinteraction = 1; + +%3dp objects +do.rgline = 1; +do.bgline = 1; +do.rbline = 1; +do.gbline = 1; +do.brline = 1; +do.grline = 1; +do.threedpcontour = 1; + +state = iconson('click3D'); +if ~state{1} + do.point3D = 0; +end + +switch DATA.ViewPanelsType{panel} + case {'hla','gla','vla'} + %Somethings are never shown in hla gla vla + do.endocontour = 0; + do.epicontour = 0; + do.rvendocontour = 0; + do.rvepicontour = 0; + do.generalpencontour = 0; + do.endointerp = 0; + do.epiinterp = 0; + do.rvendointerp = 0; + do.rvepiinterp = 0; + do.generalpeninterp = 0; + do.measures = 1; + do.point = 0; + do.croi = 0; + do.yroi = 0; + do.mroi = 0; + do.kroi = 0; + do.groi = 0; + do.rroi = 0; + do.broi = 0; + do.wroi = 0; + do.text = 1; + do.intersections = 1; + do.scar = 0; + do.mar = 0; + do.manualinteraction = 0; + + %3dp objects + do.rgline = 0; + do.bgline = 0; + do.rbline = 0; + do.gbline = 0; + do.brline = 0; + do.grline = 0; + do.threedpcontour = 0; + %do.rcontour = 0; + %do.bcontour = 0; + %do.gcontour= 0; + %do.scontour= 0; + + %measures----------------------------------------------- + if ~isempty(SET(no).Measure) + [measure,slice] = viewfunctions('getmeasurecoords',panel); + measureinslice = zeros(1,length(SET(no).Measure)); + for loop=1:length(SET(no).Measure) + ziv = round(measure(loop).Z); + ziv = min(ziv):max(ziv); + if ismember(slice,ziv) + measureinslice(loop) = 1; + break; + end + end + else + measureinslice =0; + end + + if ~any(measureinslice) + do.measures = 0; + set(DATA.Handles.measurement(panel),'XData', nan, 'YData', nan); + set(DATA.Handles.measurementoutsideplane(panel),'XData', nan, 'YData', nan); + set(DATA.Handles.measurementtext(panel,:),'position',[nan nan]); + end + + case {'trans3DP','sag3DP','cor3DP','speedim'} + %Somethings are never shown in 3DP views + do.endocontour = 0; + do.epicontour = 0; + do.rvendocontour = 0; + do.rvepicontour = 0; + do.generalpencontour = 0; + do.endointerp = 0; + do.epiinterp = 0; + do.rvendointerp = 0; + do.rvepiinterp = 0; + do.generalpeninterp = 0; + do.measures = 0; + do.point = 1; + do.croi = 0; + do.yroi = 0; + do.mroi = 0; + do.kroi = 0; + do.groi = 0; + do.rroi = 0; + do.broi = 0; + do.wroi = 0; + do.text = 1; + do.intersections = 0; + do.scar = 0; + do.mar = 0; + do.manualinteraction = 0; + + %get panels shown and do the intersection lines based on that + panels = ismember({'trans3DP','sag3DP','cor3DP','speedim'},DATA.ViewPanelsType); + + %Check which combinations there are +% if length(DATA.ViewPanelsType)>2 +% +% do.rgline = panels(1)*panels(2); +% do.rbline = panels(1)*panels(3); +% do.bgline = panels(3)*panels(2); +% do.brline = panels(3)*panels(1); +% do.gbline = panels(2)*panels(3); +% do.grline = panels(2)*panels(1); +% end + + paneltype = DATA.ViewPanelsType{panel}; + if isequal(paneltype,'speedim') + switch SET(no).LevelSet.Pen.Color + case 'r' + paneltype = 'trans3DP'; + case 'g' + paneltype = 'sag3DP'; + case 'b' + paneltype = 'cor3DP'; + end + end + + switch paneltype + case 'trans3DP' + do.rgline = 1; + do.rbline = 1; + do.grline = 0; + do.gbline = 0; + do.brline = 0; + do.bgline = 0; + %currenttype = 'r'; + currentind = 1; + case 'sag3DP' + do.rgline = 0; + do.rbline = 0; + do.grline = 1; + do.gbline = 1; + do.brline = 0; + do.bgline = 0; + %currenttype = 'g'; + currentind = 2; + case 'cor3DP' + do.rgline = 0; + do.rbline = 0; + do.grline = 0; + do.gbline = 0; + do.brline = 1; + do.bgline = 1; + + %currenttype = 'b'; + currentind = 3; + end + + %for the contours we need to check the show contour button + outlineon = findindented(DATA.Handles.configiconholder,'outline'); + + %default is off + do.threedpcontour = 0; + %do.rcontour = 0; + %do.bcontour = 0; + %do.gcontour= 0; + %do.scontour= 0; + + %do.([currenttype 'contour']) = outlineon*panels(currentind); + do.threedpcontour = outlineon*panels(currentind); + + types = {'rg','gr','rb','br','bg','gb'}; + for i = 1:length(types) + if ~do.([types{i},'line']) + DATA.Handles.([types{i},'line'])(panel).XData = [nan nan]; + DATA.Handles.([types{i},'line'])(panel).YData = [nan nan]; + end + end + + %if ~do.([currenttype,'contour']) + if ~do.threedpcontour + DATA.Handles.threedpcontour(panel).ZData = [127 0 ; 0 0]; + end + + %points in 3d + %points--------------------------------------------------- + switch DATA.ViewPanelsType{panel} + case 'trans3DP' + [~,ind] = findfunctions('closestpoint3dp',panel,1,1,SET(no).LevelSet.View.RSlice); + case 'sag3DP' + [~,ind] = findfunctions('closestpoint3dp',panel,1,1,SET(no).LevelSet.View.GSlice); + case 'cor3DP' + [~,ind] = findfunctions('closestpoint3dp',panel,1,1,SET(no).LevelSet.View.BSlice); + otherwise + ind = []; + end + + if isempty(ind) + do.point=0; + set(DATA.Handles.point(panel),'XData', nan, 'YData', nan); + set(DATA.Handles.pointtext(panel,:),'position',[nan nan]); + end + + case 'viewport' + %the viewport panel has no annotations whatsoever. + do.endocontour = 0; + do.epicontour = 0; + do.rvendocontour = 0; + do.rvepicontour = 0; + do.generalpencontour = 0; + do.endointerp = 0; + do.epiinterp = 0; + do.rvendointerp = 0; + do.rvepiinterp = 0; + do.generalpeninterp = 0; + do.measures = 0; + do.point = 0; + do.croi = 0; + do.yroi = 0; + do.mroi = 0; + do.kroi = 0; + do.groi = 0; + do.rroi = 0; + do.broi = 0; + do.wroi = 0; + do.text = 0; + do.intersections = 0; + do.scar = 0; + do.mar = 0; + do.manualinteraction = 0; + + %3dp objects + do.rgline = 0; + do.bgline = 0; + do.rbline = 0; + do.gbline = 0; + do.brline = 0; + do.grline = 0; + do.threedpcontour = 0; + %do.rcontour = 0; + %do.bcontour = 0; + %do.gcontour= 0; + %do.scontour= 0; + + otherwise + %3dp objects + do.rgline = 0; + do.bgline = 0; + do.rbline = 0; + do.gbline = 0; + do.brline = 0; + do.grline = 0; + do.threedpcontour = 0; + %do.rcontour = 0; + %do.bcontour = 0; + %do.gcontour= 0; + %do.scontour= 0; + + + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + %contours------------------------------------------------- + for i = 1:length(types) + ind = findfunctions('findframeswithsegmentation',types{i},no,slices); + + if ~any(ind) + do.([lower(types{i}),'contour']) = 0; + set(DATA.Handles.([lower(types{i}),'contour'])(panel), ... + 'XData', nan, 'YData', nan) + end + end + + types = {'Endo','Epi','RVEndo','RVEpi','GeneralPen'}; + %interpolationpoints-------------------------------------- + for i = 1:length(types) + ind = findfunctions('findframeswithinterpolationpoints',types{i},no,slices); + + if ~any(ind) + do.([lower(types{i}),'interp']) = 0; + set(DATA.Handles.([lower(types{i}),'interp'])(panel), ... + 'XData', nan, 'YData', nan) + end + end + + + %rois---------------------------------------------------- + linkednos = SET(no).Linked; + colors = []; + for i = 1:length(linkednos) + roisinslice = cellfun(@(x) any(~isempty(x)) && any(x==slices),{SET(linkednos(i)).Roi.Z}); + ls = [SET(linkednos(i)).Roi(roisinslice).LineSpec]; + ls = ls(1:2:end); + colors = [colors,unique(ls)]; + + %The roicurrent is set to nan if it isnt in the viewed slices + if ~any(SET(linkednos(i)).RoiCurrent == find(roisinslice)) + set(DATA.Handles.roicurrent(panel),... + 'XData', nan, 'YData', nan); + set(DATA.Handles.roitext(panel,:),'Position',[nan nan]); + end + end + + colorlist = 'cgykmwrb'; + notincludedcolors = colorlist(~ismember(colorlist,colors)); + + for c = notincludedcolors + set(DATA.Handles.([c,'roi'])(panel),... + 'XData', nan, 'YData', nan); +% % % set(DATA.Handles.([c,'roitext'])(panel,:),... +% % % 'Position', [nan,nan]); +% set(DATA.Handles.roitext(panel,:),... +% 'Position', [nan,nan]); + do.([c,'roi']) = 0; + end + + %points--------------------------------------------------- + if ~any(ismember(SET(no).Point.Z,slices)) + do.point=0; + set(DATA.Handles.point(panel),'XData', nan, 'YData', nan); + set(DATA.Handles.pointtext(panel,:),'position',[nan nan]); + end + + %Scar------------------------------------------------------ + %For the contour objects the equivalent of nan rendering is placing a zero matix with a one in a corner. +% visibleslices = viewfunctions('slicesinpanel', panel) + if isempty(SET(no).Scar) + tmp = [1,0;0,0]; + set([DATA.Handles.scarcontour(panel),DATA.Handles.weightedscarcontour(panel),... + DATA.Handles.moextentcontour(panel),DATA.Handles.mocontour(panel)],'ZData',tmp,'YData',tmp,'XData',tmp); + do.scar = 0; + do.manualinteraction = 0; + elseif ~any(SET(no).Scar.Result(:,:,slices),'all') + tmp = [1,0;0,0]; + set([DATA.Handles.scarcontour(panel),DATA.Handles.weightedscarcontour(panel),... + DATA.Handles.moextentcontour(panel),DATA.Handles.mocontour(panel)],'ZData',tmp,'YData',tmp,'XData',tmp); + do.scar = 0; + do.manualinteraction = 0; + elseif ~any(SET(no).Scar.NoReflow(:,:,slices),'all') + tmp = [1,0;0,0]; + set([DATA.Handles.moextentcontour(panel),DATA.Handles.mocontour(panel)],'ZData',tmp,'YData',tmp,'XData',tmp); + end + + %Since manual interaction is incorporated into the panel + %imagehandle we need to check the button state here + stateandicon = iconson('hidescarmanual'); + if stateandicon{1} + do.manualinteraction = 0; + end + + %Mar-------------------------------------------------------- + if isempty(SET(no).MaR) + %no one can see it anyway + tmp = [1,0;0,0]; + set(DATA.Handles.marcontour(panel),'ZData',tmp,'YData',tmp,'XData',tmp); + do.mar = 0; + %JB 2019-11-06 commented out so users can draw mar even in time-resolved + %data +% elseif ~any(SET(no).MaR.Result(:,:,visibleslices),'all') +% %no one can see it anyway +% tmp = [1,0;0,0]; +% DATA.Handles.marcontour(panel).ZData = tmp; +% do.mar = 0; + end + + %measures--------------------------------------------------------------------- + if ~isempty(SET(no).Measure) + [measure,slice] = viewfunctions('getmeasurecoords',panel); + measureinslice = zeros(1,length(SET(no).Measure)); + for loop=1:length(SET(no).Measure) + ziv = round(measure(loop).Z); + ziv = min(ziv):max(ziv); + if ismember(slice,ziv) + measureinslice(loop) = 1; + break; + end + end + else + measureinslice =0; + end + + if ~any(measureinslice) + do.measures = 0; + set(DATA.Handles.measurement(panel),'XData', nan, 'YData', nan); + set(DATA.Handles.measurementoutsideplane(panel),'XData', nan, 'YData', nan); + set(DATA.Handles.measurementtext(panel,:),'position',[nan nan]); + end +end + + +%--------------------- +function updatevisibility %#ok +%----------------------- +global DATA + +%Turn all on first +set(DATA.Handles.marcontour,'Visible', 'on'); +set(DATA.Handles.planeintersection,'Visible','on'); +set(DATA.Handles.scarcontour,'Visible', 'on'); +set(DATA.Handles.weightedscarcontour,'Visible', 'on'); %Weighted scar contour +set(DATA.Handles.moextentcontour,'Visible', 'on'); +set(DATA.Handles.mocontour,'Visible', 'on'); +set(DATA.Handles.endocontourintersection,'Visible', 'on'); +set(DATA.Handles.epicontourintersection,'Visible', 'on'); +set(DATA.Handles.rvendocontourintersection,'Visible', 'on'); +set(DATA.Handles.rvepicontourintersection,'Visible', 'on'); +set([DATA.Handles.endointerp, ... + DATA.Handles.epiinterp, ... + DATA.Handles.rvendointerp, ... + DATA.Handles.rvepiinterp,... + DATA.Handles.endocontour, ... + DATA.Handles.epicontour,... + DATA.Handles.rvendocontour, ... + DATA.Handles.rvepicontour],'Visible', 'on'); +set(DATA.Handles.roicurrent,'Visible','on'); +set([DATA.Handles.croi,... + DATA.Handles.rroi,... + DATA.Handles.mroi,... + DATA.Handles.kroi,... + DATA.Handles.groi,... + DATA.Handles.wroi,... + DATA.Handles.yroi,... + DATA.Handles.broi],... + 'visible','on') +set(DATA.Handles.roitext(:),'Visible','on'); +% set([DATA.Handles.croitext(:),... +% DATA.Handles.rroitext(:),... +% DATA.Handles.mroitext(:),... +% DATA.Handles.kroitext(:),... +% DATA.Handles.groitext(:),... +% DATA.Handles.wroitext(:),... +% DATA.Handles.yroitext(:),... +% DATA.Handles.broitext(:)],... +% 'Visible','on'); +%set(DATA.Handles.roitext,'Visible','on'); +set(DATA.Handles.measurement,'Visible','on'); +set(DATA.Handles.measurementtext,'Visible','on'); +set(DATA.Handles.point,'Visible','on'); +set(DATA.Handles.point3D,'Visible','on'); +set(DATA.Handles.pointtext,'Visible','on'); +set(DATA.Handles.text,'Visible','on'); +set(DATA.Handles.centercross,'Visible', 'on'); + +%The do structures contains information of which updates to use. +tmp = cell(1,length(DATA.ViewPanels)); +for i = 1:length(tmp) + tmp{i} = 1; +end + +do = struct('endocontour',tmp,'epicontour',tmp,'rvendocontour',tmp,'rvepicontour',tmp,'generalpencontour',tmp... + ,'endointerp',tmp,'epiinterp',tmp,'rvendointerp',tmp,'rvepiinterp',tmp,'generalpeninterp',tmp,... + 'measures',tmp,'point',tmp,'point3D',tmp,'croi',tmp,'mroi',tmp,'groi',tmp,'rroi',tmp,... + 'broi',tmp,'wroi',tmp,'yroi',tmp,'kroi',tmp,'text',tmp,... + 'intersections',tmp,'scar',tmp,'mar',tmp,'manualinteraction',tmp,... + 'rgline',tmp,'bgline',tmp,'rbline',tmp,'gbline',tmp,'brline',tmp,... + 'grline',tmp,'threedpcontour',tmp); + +%Then we perform a check if there exists objects in any of the timeframes +%for contours interpolation points measures rois viability %this is done on panel level so if no segmentatio found in panel then it is +%not displayed in that panel; +for p = find(DATA.ViewPanels) + do(p) = viewfunctions('annotationinpanel',p); +end + +%Then hide icons are incorporated. The hide state is set for all panels so +%if a state is hidden then that is applied for all panels. +hidecell={'hideplus','hidemar','hidescar',... + 'hideintersections','hideothercontour',... + 'hideinterp','hidelv','hiderv','hideroi',... + 'hidemeasure','hidepoint','hidetext','hidescarmanual'};%'hidescarextent','hidescarmanual'}; + +stateandicon = iconson(hidecell); +availableicons = cellfun(@(x) isa(x,'myicon'),stateandicon(:,2)); +% state=[stateandicon{availableicons,1}]; +state = [stateandicon{:,1}]; + +% First state corresponds to centercross +if state(1) + set(DATA.Handles.centercross,'Visible', 'off'); +end + +%Second state corresponds to the marcontour. +if state(2) + set(DATA.Handles.marcontour,'Visible', 'off'); + %remake images without manual interaction + DATA.ViewIM = cell(size(DATA.ViewIM)); +end + +%Third state corresponds to the scarcontour. +if state(3) + set(DATA.Handles.scarcontour,'Visible', 'off'); + set(DATA.Handles.weightedscarcontour,'Visible', 'off'); %Weighted scar contour + set(DATA.Handles.moextentcontour,'Visible', 'off'); + set(DATA.Handles.mocontour,'Visible', 'off'); + %remake images without manual interaction visually turned off at bottom + %of function + DATA.ViewIM = cell(size(DATA.ViewIM)); + [do.scar] = deal(0); + [do.manualinteraction] = deal(0); +end + +%Fourth state corresponds to the plane intersections. +if state(4) + set(DATA.Handles.planeintersection,'Visible','off'); +end + +%Fifth state corresponds to the contour intersections. +if state(5) + set(DATA.Handles.endocontourintersection,'Visible', 'off'); + set(DATA.Handles.epicontourintersection,'Visible', 'off'); + set(DATA.Handles.rvendocontourintersection,'Visible', 'off'); + set(DATA.Handles.rvepicontourintersection,'Visible', 'off'); + [do.intersections] = deal(0); +end + +%Sixth state corresponds to the interpolationpoints. +if state(6) + iph = mycat(2,DATA.Handles.endointerp, ... + DATA.Handles.epiinterp, ... + DATA.Handles.rvendointerp, ... + DATA.Handles.rvepiinterp); + set(iph,'Visible', 'off'); + [do.interp] = deal(0); +end + +%Seventh state corresponds to LV contours +if state(7) + lvh = mycat(2, DATA.Handles.endocontour, ... + DATA.Handles.epicontour,... + DATA.Handles.endointerp, ... + DATA.Handles.epiinterp, ... + DATA.Handles.endocontourintersection, ... + DATA.Handles.epicontourintersection); + set(lvh,'Visible', 'off'); + [do.intersections] = deal(0); +end + +%Eigth state corresponds to RV contours +if state(8) + rvh = mycat(2, DATA.Handles.rvendocontour, ... + DATA.Handles.rvepicontour,... + DATA.Handles.rvendointerp, ... + DATA.Handles.rvepiinterp, ... + DATA.Handles.rvendocontourintersection, ... + DATA.Handles.rvendocontourintersection); + set(rvh,'Visible', 'off'); + [do.intersections] = deal(0); +end + +%nineth state corresponds to Rois +if state(9) + set(DATA.Handles.roicurrent,'Visible','off'); + set([DATA.Handles.croi,... + DATA.Handles.rroi,... + DATA.Handles.mroi,... + DATA.Handles.kroi,... + DATA.Handles.groi,... + DATA.Handles.wroi,... + DATA.Handles.yroi,... + DATA.Handles.broi],... + 'visible','off') +% % % set([DATA.Handles.croitext(:),... +% % % DATA.Handles.rroitext(:),... +% % % DATA.Handles.mroitext(:),... +% % % DATA.Handles.kroitext(:),... +% % % DATA.Handles.groitext(:),... +% % % DATA.Handles.wroitext(:),... +% % % DATA.Handles.yroitext(:),... +% % % DATA.Handles.broitext(:)],... +% % % 'Visible','off'); + set(DATA.Handles.roitext(:),'Visible','off'); + [do.roi] = deal(0); +end + +%Tenth state corresponds to measures +if state(10) + set(DATA.Handles.measurement,'Visible','off'); + set(DATA.Handles.measurementtext,'Visible','off'); + [do.measures] = deal(0); +end + +%Eleventh state corresponds to points +if state(11) + set(DATA.Handles.point,'Visible','off'); + set(DATA.Handles.pointtext,'Visible','off'); + [do.point] = deal(0); +end + +%Twelveth state corresponds to text +if state(12) + set(DATA.Handles.text,'Visible','off'); + set(DATA.Handles.pointtext,'Visible','off'); + set(DATA.Handles.measurementtext,'Visible','off'); + set(DATA.Handles.roitext(:),'Visible','off'); + [do.text] = deal(0); +end + +% %Thirteenth state corresponds to extent +% if state(13) +% set(DATA.Handles.moextentcontour,'Visible', 'off') +% end + +%fourteenth state corresponds to manual interaction +if state(13) + DATA.ViewIM = cell(size(DATA.ViewIM)); + [do.manualinteraction] = deal(0); +end + +% add to drawlist what updates need to be made. +DATA.drawlist = cell(1,length(DATA.ViewPanels)); + +%Drawlist is a cell of cells +for p = 1:length(DATA.ViewPanels) + DATA.drawlist{p} = {}; +end + +%this only updates the draw list +for p = find(DATA.ViewPanels) + updatedrawlist_helper(p,do(p)) +end + +%this resets images where we've hidden on off manual interaction +for p = find(DATA.ViewPanels)%p = find(cellfun(@isempty,DATA.ViewIM)) + drawfunctions('drawpanel',p)%drawfunctions('drawpanel',p) +end + +%------------------------------------------------------------------------ +function selectroi(panel) %#ok +%------------------------------------------------------------------------ +%Function that sets currentroi and updates the graphics +global DATA SET +no = DATA.ViewPanels(panel); +if not(isempty(SET(no).Flow)) && isfield(SET(no).Flow,'MagnitudeNo') && not(isempty(SET(no).Flow.MagnitudeNo)) + magno = SET(no).Flow.MagnitudeNo; +else + magno = no; +end +[y,x] = mygetcurrentpoint(DATA.Handles.imageaxes(panel)); +slice = viewfunctions('clickedslice',panel,x,y); +slicestoinclude = slicesinpanel(panel); +scale = getscale(panel); + +%only work with rois that exist in the included slices +roistodo = find(cellfun(@(x) ~isempty(x) && any(x==slicestoinclude),{SET(magno).Roi.Z})); +dist2 = zeros(1,length(roistodo)); + +%get clicked position + +for loop=1:length(roistodo) + [xl,yl] = ind2sub(DATA.ViewPanelsMatrix{panel},find(slicestoinclude==SET(magno).Roi(roistodo(loop)).Z)); + yl = (yl-1)*SET(no).YSize; + xl = (xl-1)*SET(no).XSize; + dist2(loop) = min((scale*(xl+SET(magno).Roi(roistodo(loop)).Y(:,SET(no).CurrentTimeFrame))-y).^2 + ... + (scale*(yl+SET(magno).Roi(roistodo(loop)).X(:,SET(no).CurrentTimeFrame))-x).^2); +end + +[val,ind] = min(dist2); +if sqrt(val)< DATA.Pref.ContourAdjustDistance%3 + currentroi = roistodo(ind); +else + currentroi = []; +end + +oldcurrentroi = SET(magno).RoiCurrent; +if ~isempty(currentroi) + SET(magno).RoiCurrent = currentroi; + + for p = find(ismember(DATA.ViewPanels,SET(no).Linked)) + drawfunctions('drawroi',p);%,SET(magno).Roi(currentroi).LineSpec(1)) + end +% % % for p = find(ismember(DATA.ViewPanels,SET(no).Linked)) +% % % drawfunctions('drawroi',p,SET(magno).Roi(oldcurrentroi).LineSpec(1)) +% % % end + + segment('updateflow') +end + +%--------------------- +function setviewtype(viewpanelstype) +%----------------------- +%Changes viewtype for current +global DATA NO SET + +if strcmp(viewpanelstype,'montage') && SET(NO).ZSize>100 + if not(yesno('Image stack consist of many slices, this may take some seconds to display. Continue to montage view anyway?')) + return; + end +end + +if DATA.ViewPanels(DATA.CurrentPanel) == 0 + return +end + +%If we are in orthoview mode we need to reset to single panel +if any(strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},{'orth','hla','gla','vla'})) + viewfunctions('setview',1,1,NO,{'one'}) + return +end + +DATA.ViewPanelsType{DATA.CurrentPanel} = viewpanelstype; + +if (strcmp(DATA.ViewPanelsType{DATA.CurrentPanel},'one'))&&(isempty(SET(NO).CurrentSlice)) + SET(NO).CurrentSlice = 1; + SET(NO).EndSlice = 1; + SET(NO).StartSlice = 1; +else + SET(NO).CurrentSlice = min(SET(NO).EndSlice,max(SET(NO).StartSlice,SET(NO).CurrentSlice)); +end + +if ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montage','montagerow','montagesegmented'}) + if ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montagesegmented'}) + slicestoshow = slicesinpanel(DATA.CurrentPanel); + [mrows,mcols] = calcfunctions('calcrowscols',DATA.ViewPanels(DATA.CurrentPanel),length(slicestoshow)); + else + [mrows,mcols] = calcfunctions('calcrowscols',DATA.ViewPanels(DATA.CurrentPanel)); + end + if ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montagerow'}) + m = mrows*mcols; + mrows = min(mrows,2); + mcols = ceil(m/mrows); + end + DATA.ViewPanelsMatrix{DATA.CurrentPanel} = [mcols mrows]; +else + DATA.ViewPanelsMatrix{DATA.CurrentPanel} = [1,1]; +end + +%Assert correct button is indented +DATA.setviewbuttons(0) + +%this draws and updates the panel image intersections. +drawfunctions('drawplaneintersections') +drawfunctions('drawpoint3D') + +%clears current viewim +DATA.ViewIM{DATA.CurrentPanel}=[]; + +%get the drawlist and draw panels. +updatedrawlist(DATA.CurrentPanel) +drawfunctions('drawpanel',DATA.CurrentPanel) + +drawfunctions('drawselectedframe',DATA.CurrentPanel) +drawfunctions('drawselectedslice',DATA.CurrentPanel) +updatetextposition(DATA.CurrentPanel) + +%--------------------- +function addno2panel(panel,no,viewpanelstype,checklinked) +%----------------------- +%Adds a no to a panel. The viewtype is one by default +global DATA SET NO +%profile on +if nargin < 4 + checklinked = true; +end +if nargin <3 + viewpanelstype = 'one'; +end +if nargin < 2 + no = NO; +end + +%Apply all settings +DATA.CurrentPanel = panel; +previousno = DATA.ViewPanels(panel); +for num = 1:numel(DATA.ViewPanels) + DATA.Handles.point3D(num).XData(:) = nan; + DATA.Handles.point3D(num).YData(:) = nan; +end +if previousno > 0 && length(SET(previousno).Linked) == 2 && checklinked + % this was a stack with linked stacks + % so check if the linked stack were also visible + linkedpanelsind = find(ismember(DATA.ViewPanels,setdiff(SET(previousno).Linked,previousno))); + if ~isempty(linkedpanelsind) && length(SET(no).Linked) == 2 + % look if the new no is also linked + linkedstack = setdiff(SET(no).Linked,no); + if numel(linkedpanelsind) > 1 + paneldist = linkedpanelsind - panel; + paneldist(paneldist<0) = Inf; + linkedpanelsind = linkedpanelsind(paneldist == min(paneldist)); + end + % set linked panel first to ensure that the clicked one is set to NO + addno2panel(linkedpanelsind(1),linkedstack,viewpanelstype, false) + end +end +DATA.ViewPanels(panel) = no; +DATA.ViewPanelsType{panel} = viewpanelstype; + +if ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montage','montagerow'}) + [mrows,mcols] = calcfunctions('calcrowscols',DATA.ViewPanels(DATA.CurrentPanel)); + if ismember(DATA.ViewPanelsType{DATA.CurrentPanel},{'montagerow'}) + m = mrows*mcols; + mrows = min(mrows,2); + mcols = ceil(m/mrows); + end + DATA.ViewPanelsMatrix{DATA.CurrentPanel} = [mcols mrows]; +else + DATA.ViewPanelsMatrix{DATA.CurrentPanel} = [1,1]; +end + +DATA.ViewIM{panel} = []; +NO = no; + +%get the drawlist and draw panels. +updatedrawlist(panel) + +%update altered panels fully +panelslinked = find(ismember(DATA.ViewPanels,SET(no).Linked)); +for p = panelslinked + drawfunctions('drawpanel',p) +end + +%this draws and updates the panel image intersections. +drawfunctions('drawplaneintersections') +drawfunctions('drawintersections') %empty input udpate all viewpanels + +drawfunctions('drawselectedframe',panel) +drawfunctions('drawselectedslice',panel) +drawfunctions('drawthumbnails',isempty(DATA.DATASETPREVIEW)); +%drawfunctions('drawthumbnailframes') +createfunctions('addcolorbar',panel) +updatetextposition(panel) + +%Assert correct button is indented +DATA.setviewbuttons(0) +if strcmp(DATA.ProgramName,'Segment') + segment('updatevolume'); +elseif contains(DATA.ProgramName,'CMR') + % update volume axes + DATA.updatevolumeaxes; +end +segment('updateflow'); +segment('updatemeasurement'); +DATA.updatetimebaraxes + + +%--------------------- +function switchimagestack(no,viewpanelstype) %#ok +%----------------------- +%Toggles to the first panel containing imagestack no. In the code it finds +%the first panel containing no and then uses switchpanel to switch to it +global DATA +panel = find(DATA.ViewPanels==no,1); + +%if the imagestack is not out then add it to the first place +if isempty(panel) + switchpanel(panel); +end + +if nargin >1 + if ~strcmp(viewpanelstype,DATA.ViewPanelsType{panel}) + setviewtype(viewpanelstype) + end +end + +%----------------------------- +function speedim = findspeedim +%----------------------------- +%Returns panel for speedim otherwise empty + +global DATA + +speedim = find(strcmp(DATA.ViewPanelsType,'speedim')); + +%--------------------------------------------- +function zoomstate = getnewzoomstate(panel,no, resetflag) +%--------------------------------------------- +%Compute initialization of zoom state + +global DATA SET +if nargin<3 + resetflag = true; +end +switch DATA.ViewPanelsType{panel} + case 'trans3DP' + color = 'r'; + [xsize,ysize,~,~] = segment3dp.tools('viewsizeandres',color,no); + case 'sag3DP' + color = 'g'; + [xsize,ysize,~,~] = segment3dp.tools('viewsizeandres',color,no); + case 'cor3DP' + color = 'b'; + [xsize,ysize,~,~] = segment3dp.tools('viewsizeandres',color,no); + case 'speedim' + if isempty(SET(no).LevelSet) %~isfield(SET(no).LevelSet.Pen,'Color') + color= 'r'; + else + color = SET(no).LevelSet.Pen.Color; + end + [xsize,ysize,~,~] = segment3dp.tools('viewsizeandres',color,no); + otherwise + xsize = SET(no).XSize; + ysize = SET(no).YSize; +end + +%Find panelsize +panelpos = DATA.Handles.imageaxes(panel).Position; +figpos = DATA.fig.Position; +panelwidth = panelpos(3)*figpos(3)/ysize; +panelheight = panelpos(4)*figpos(4)/xsize; + +%maxsize = max(SET(no).XSize,SET(no).YSize); +minpanelsize = min(panelwidth,panelheight); +panelwidth = panelwidth/minpanelsize; %range 1.. +panelheight = panelheight/minpanelsize; %range 1.. + +xcenter = xsize/2; +ycenter = ysize/2; + +zoomstate = [... + ycenter-panelwidth*ysize/2 ... + ycenter+panelwidth*ysize/2 ... + xcenter-panelheight*xsize/2 ... + xcenter+panelheight*xsize/2]+0.5; + +if resetflag + switch DATA.ViewPanelsType{panel} + case 'trans3DP' + SET(no).LevelSet.View.RZoomState = zoomstate; + case 'sag3DP' + SET(no).LevelSet.View.GZoomState = zoomstate; + case 'cor3DP' + SET(no).LevelSet.View.BZoomState = zoomstate; + case 'speedim' + %nothing + case 'one' + SET(no).NormalZoomState = zoomstate; + end +end + +%------------------ +function zoom(incr,panel) +%------------------ +%New solution for zooming + +global DATA SET + +if nargin < 2 + %Get panel + panel = DATA.CurrentPanel; +end + +if ~isempty(DATA.LastKey) && strcmp(DATA.LastKey,'shift') + % all visible NOs + nos = DATA.ViewPanels(DATA.ViewPanels > 0); + linkedpanelsindx = find(DATA.ViewPanels > 0); + noslinked = 0; +else + %Get no + no = DATA.ViewPanels(panel); + noslinked = SET(no).Linked; + %Get linked panels + [nos,~,linkedpanelsindx] = intersect(noslinked,DATA.ViewPanels); +end + +%loop over linked stacks +for loop = 1:length(nos) + + %extract current stack + no = nos(loop); + panel = linkedpanelsindx(loop); + %check if 3dp + is3dp = ismember(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','cor3DP','speedim'}); + + if is3dp + color = SET(no).LevelSet.Pen.Color; + zoomstate = SET(no).LevelSet.View.([upper(color) 'ZoomState']); %get zoomstate + else + zoomstate = SET(no).NormalZoomState; %get zoomstate + end + + if isempty(zoomstate) + zoomstate = getnewzoomstate(panel,no); + end + + %Here occurs the zoom! + + %Compute x&y size and center + xsize = zoomstate(2)-zoomstate(1); + ysize = zoomstate(4)-zoomstate(3); + xcenter = sum(zoomstate(1:2))/2; + ycenter = sum(zoomstate(3:4))/2; + + %Compute factor + f = 1-incr/7; + + %Compute newzoom state based on the center and how much to extend + newzoomstate = [xcenter-xsize/2*f xcenter+xsize/2*f ycenter-ysize/2*f ycenter+ysize/2*f]; + + if ~is3dp + %assign + if all(noslinked ~= 0) && ~all(nos == noslinked) + % set also the invisble nos to the same Zoomstate + ind = nos ~= noslinked; + numnos = length(ind); + if numnos > 1 + for cl = 2:numnos + SET(ind(cl)).NormalZoomState = []; + end + end + end + SET(no).NormalZoomState = newzoomstate; + + %update it graphically + updatezoomandaspectratio(panel); + drawfunctions('drawplaneintersections'); + %we want to update the text position and the frame + drawfunctions('drawselectedframe',panel) + updatetextposition(panel) + else + %--- special for 3DP + + %assign + SET(no).LevelSet.View.([upper(color) 'ZoomState']) = newzoomstate; + + speedimpanel = findspeedim; + + %find color panel + color = SET(no).LevelSet.Pen.Color; + switch color + case 'r' + panelname = 'trans3DP'; + case 'g' + panelname = 'sag3DP'; + case 'b' + panelname = 'cor3DP'; + end + + colorpanel = find(strcmp(DATA.ViewPanelsType,panelname)); + + %update it graphically + if ~isempty(speedimpanel) + updatezoomandaspectratio(speedimpanel); + drawfunctions('drawselectedframe',speedimpanel) + updatetextposition(speedimpanel) + end + if ~isempty(colorpanel) + updatezoomandaspectratio(colorpanel); + drawfunctions('drawselectedframe',colorpanel) + updatetextposition(colorpanel) + end + end +end + +%--------------------- +function updatetextposition(panel) +%----------------------- +%This function updates the text position after updates such as zooming or +%panning + +global DATA + +x = max(0.5,0.015*(DATA.Handles.imageaxes(panel).XLim(2)-DATA.Handles.imageaxes(panel).XLim(1))); +y = max(0.5,0.015*(DATA.Handles.imageaxes(panel).YLim(2)-DATA.Handles.imageaxes(panel).YLim(1))); +DATA.Handles.text(panel).Position = [DATA.Handles.imageaxes(panel).XLim(1)+x,DATA.Handles.imageaxes(panel).YLim(1)+y]; + +%-------------------------- +function switchpanel(panel) +%-------------------------- +%Toggles the CurrentPanel and NO to be correct aswell as does the necessary +%graphical updates. If trying to toggle to an empty panel dont change +%anything + +global DATA SET NO + +no = DATA.ViewPanels(panel); + +%this is the empty panel case +if no ~= 0 + DATA.CurrentPanel = panel; + NO = no; + drawfunctions('drawselectedframe',panel) + drawfunctions('drawthumbnailframes') +end + +%this draws and updates the panel image intersections. +drawfunctions('drawplaneintersections') + +%checks if switching 3DP panel to 3DP panel if so we need to update the +%current color and speedimage +if any(strcmp(DATA.ViewPanelsType(DATA.CurrentPanel),{'trans3DP','sag3DP','cor3DP'})) + + %Check if switching to new color + switch DATA.ViewPanelsType{panel} + case 'trans3DP' + newcolor = 'r'; + case 'sag3DP' + newcolor = 'g'; + case 'cor3DP' + newcolor = 'b'; + end + + %Store new color + if SET(no).LevelSet.Pen.Color ~= newcolor + SET(no).LevelSet.Pen.Color = newcolor; + speedpanel = find(strcmp(DATA.ViewPanelsType,'speedim')); + if ~isempty(speedpanel) + + DATA.ViewIM{speedpanel} = []; + %drawfunctions('drawimages',speedpanel); + drawfunctions('drawpanel',speedpanel) + + %Remove all lines + h = [... + DATA.Handles.rgline(speedpanel) ... + DATA.Handles.rbline(speedpanel) ... + DATA.Handles.grline(speedpanel) ... + DATA.Handles.gbline(speedpanel) ... + DATA.Handles.brline(speedpanel) ... + DATA.Handles.bgline(speedpanel)]; + + set(h,'xdata',NaN,'ydata',NaN); + + %add new liness + switch newcolor + case 'r' + drawfunctions('draw3dpline',speedpanel,'rg'); + drawfunctions('draw3dpline',speedpanel,'rb'); + case 'g' + drawfunctions('draw3dpline',speedpanel,'gr'); + drawfunctions('draw3dpline',speedpanel,'gb'); + case 'b' + drawfunctions('draw3dpline',speedpanel,'br'); + drawfunctions('draw3dpline',speedpanel,'bg'); + end + + %Update text position on speedpanel + viewfunctions('updatetextposition',speedpanel) + end + end + +end + +DATA.setviewbuttons(0); +if strcmp(DATA.ProgramName,'Segment') + segment('updatevolume'); +end +segment('updateflow'); +segment('updatemeasurement'); +DATA.updatetimebaraxes; + +%------------------------------------- +function placecontextmenu(panel,type,objectind) %#ok +%------------------------------------- +%Function that returns the clicked slice in montage and montage +global DATA SET NO + +[p(1),p(2)] = mygetcurrentpoint(DATA.fig); + +switch type + case 'Measure' + set(DATA.Handles.measurecontextmenu,... + 'Position',p,'Visible','on'); + case 'Point' + set(DATA.Handles.pointcontextmenu,... + 'Position',p,'Visible','on'); + case {'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'} + set(DATA.Handles.interppointmenu,... + 'Position',p,'Visible','on'); + case 'Roi' + % set current roi to the clicked object in (objectind) + SET(NO).RoiCurrent = objectind; + drawfunctions('drawroi',panel); + set(DATA.Handles.roicontextmenu,... + 'Position',p,'Visible','on'); + otherwise + switch DATA.CurrentTool + case {'Endo','Epi',... + 'EndoInterp','EpiInterp','RVEndo','RVEpi','Scar',... + 'MO','MaR','ScarRubber','MORubber','MaRRubber',... + 'RVEndoInterp','RVEpiInterp','GeneralPenInterp',... + 'GeneralPen','EndoBalloon','Contrast'} + set(DATA.Handles.lvcontextmenu,... + 'Position',p,'Visible','on'); + + otherwise + set(DATA.Handles.selectcontextmenu,... + 'Position',p,'Visible','on'); + end +end + +%------------------------------------------------------------------------ +function slice = clickedslice(panel,x,y) %#ok +%------------------------------------------------------------------------ +%Function that returns the clicked slice in montage and montage +global DATA SET +no = DATA.ViewPanels(panel); + +if any(strcmp(DATA.ViewPanelsType{panel},{'trans3DP','sag3DP','speedim','cor3DP'})) + switch SET(no).LevelSet.Pen.Color + case 'r' + slice = SET(no).LevelSet.View.RSlice; + case 'g' + slice = SET(no).LevelSet.View.GSlice; + case 'b' + slice = SET(no).LevelSet.View.BSlice; + end +else + scale = getscale(panel); + x_ind = ceil(x/scale/SET(no).YSize); + y_ind = ceil(y/scale/SET(no).XSize); + + x_ind = max(x_ind,1); + x_ind = min(x_ind,DATA.ViewPanelsMatrix{panel}(1)); + + y_ind = max(y_ind,0); + y_ind = min(y_ind,DATA.ViewPanelsMatrix{panel}(2)); + + ind = sub2ind(DATA.ViewPanelsMatrix{panel},x_ind,y_ind); + + slicestoinclude = slicesinpanel(panel); + + %clicked in black area of montage + if ind>length(slicestoinclude) + slice = []; + return + end + slice = slicestoinclude(ind); +end + +%--------------------- +function setview(rows,cols,nos,viewpanelstype,currentnopanel) +%----------------------- +%Creates imageaxes and boxaxes. The field boxaxes is probably unnecessary. + +global DATA NO SET + +if DATA.Silent + return +end + +%Set information fields +%profile on +%this is the refresh option finds which viewpanelbutton is indented and +%sets rows and cols +if nargin == 0 || (isempty(rows) && isempty(cols)) + rows = DATA.ViewMatrix(1); + cols = DATA.ViewMatrix(2); + + panelnos = DATA.ViewPanels(DATA.ViewPanels>0); + for loop = panelnos + SET(loop).NormalZoomState=[]; + end + if ~isempty(SET(NO).LevelSet) + SET(NO).LevelSet.View.RZoomState = []; + SET(NO).LevelSet.View.GZoomState = []; + SET(NO).LevelSet.View.BZoomState = []; + end + +else + DATA.ViewMatrix(1) = rows; + DATA.ViewMatrix(2) = cols; +end + +%Take care of outline contours when switching from 3PD to other +%if DATA.Handles.configiconholder.findindented('outline') +% for loop = 1:length(DATA.ViewPanels) +% if ismember(DATA.ViewPanelsType{loop},{'trans3DP','sag3DP','cor3DP','speedim'}) +% drawfunctions('setxynan',loop); +% end +% end +%end + +%Delete colorbar +paneltoclean = find(DATA.ViewPanels>0); + +for i = paneltoclean + colorbar(DATA.Handles.imageaxes(i),'off') +end +specialview = false; +%We need to handle different input cases and the chance that some panels +%are empty. also the current panel might be out of bounds when toggling to +%a lesser amount of panels. Then we set the CurrentPanel and NO field to +%the first panel content using the switchpanel command +if nargin < 3 + %This is the case when we toggle to a panel view from orthoview + if any(ismember(DATA.ViewPanelsType,{'orth','hla','gla','vla'})) && nargin~=0 %if refresh keep ortho view + DATA.ViewPanels=zeros(1,rows*cols); + DATA.ViewPanels(1)=NO; + DATA.ViewPanelsType{1}='one'; + DATA.ViewPanelsType(2:end)=[]; + DATA.CurrentPanel = 1; + else %if we are going to a panelview with less panels than now just remove the last entries in DATA.ViewPanels NO and Current Panel will be set as first later + if length(DATA.ViewPanels)>rows*cols + DATA.ViewPanels = DATA.ViewPanels(1:rows*cols); + else %if we are going to a panelview with more panels than now just add zeros in ViewPanels + tmp = zeros(1,rows*cols); + tmp(1:length(DATA.ViewPanels)) = DATA.ViewPanels; + DATA.ViewPanels = tmp; + end + end + DATA.LastView = []; +else + if isempty(nos) + DATA.ViewPanels = NO*ones(1,rows*cols); + else + specialview = true; + DATA.ViewPanels = nos; + if isempty(intersect(NO,nos)) + NO = nos(1); + end + end +end + +%this takes care of if the currentpanel field is out of bounds and places +%it within the possible integers also sets the current +if nargin > 4 + %input give the panel that should be current (NO) + NO = currentnopanel(1); + DATA.CurrentPanel = currentnopanel(2); +else + if DATA.CurrentPanel > rows*cols + DATA.ViewPanels(rows*cols) = NO; + DATA.CurrentPanel = rows*cols; + end +end + +%if NO isnt among the current displayed viewpanels it is set as the stack +%in the first viewpanel +if isempty(intersect(NO,DATA.ViewPanels)) + NO = DATA.ViewPanels(1); +end + +%This asserst that viewpanelstype is set even if we dont input a cell +%specifying. If there exists prior viewpanelstype it uses it otherwise set all as one. +if nargin<4 + if isempty(DATA.ViewPanelsType) + DATA.ViewPanelsType = cell(1,length(DATA.ViewPanels)); + DATA.ViewPanelsType(:) = {'one'}; + elseif length(DATA.ViewPanelsType(:)) 0 && any(strcmp(DATA.ViewPanelsType{i},{'montage','montagerow','montagesegmented'})) + if strcmp(DATA.ViewPanelsType{i},'montagesegmented') + slicestoinclude = segment('getmontagesegmentedslices',DATA.ViewPanels(i)); + [mrows,mcols] = calcfunctions('calcrowscols',DATA.ViewPanels(i),length(slicestoinclude)); + else + [mrows,mcols] = calcfunctions('calcrowscols',DATA.ViewPanels(i)); + end + if ismember(DATA.ViewPanelsType{i},{'montagerow'}) + m = mrows*mcols; + mrows = min(mrows,2); + mcols = ceil(m/mrows); + end + DATA.ViewPanelsMatrix{i} = [mcols mrows]; + else + DATA.ViewPanelsMatrix{i} = [1,1]; + end +end + +if ~specialview + %functionality to restore same zoom state as before panel settings were + %changed + panelstodo = find(DATA.ViewPanels(DATA.ViewPanels>0)); + incr = zeros(length(panelstodo),1); + + for actpanel = panelstodo + no = DATA.ViewPanels(actpanel); + linkednos = SET(no).Linked; + numnos = length(linkednos); + if numnos > 1 + for cl = 2:numnos + SET(linkednos(cl)).NormalZoomState = []; + end + end + type = DATA.ViewPanelsType{actpanel}; + if any(contains({'one'},type)) + zoomstatecurrent = SET(no).NormalZoomState; + if ~isempty(zoomstatecurrent) + % compare current state to the original + % where original would be zoom state without zooming + zoomstateoriginal = getnewzoomstate(actpanel,no,false); + szxorig = zoomstateoriginal(2)-zoomstateoriginal(1); + szxcurrent = zoomstatecurrent(2)-zoomstatecurrent(1); + if ~isnan(szxorig) && ~isnan(szxcurrent) && ~isapproxequal(szxorig,szxcurrent) + % ratios not equal -> ther was zooming + f = szxcurrent/szxorig; + % recalculate zoom increment + incr(actpanel) = round((1-f)*7); + end + end + end + end +end + + +%This sets the preallocated axes to fit the above settings in ViewPanels +%etc... +configaxes +if any(ismember(DATA.ViewPanelsType,{'orth'})) + DATA.CurrentPanel = 1; +end + +%if we are dealing with 3dp views things are done slightly different. +if any(ismember(DATA.ViewPanelsType,{'trans3DP','sag3DP','cor3DP','speedim','viewport'})) + + %check 3dp fields asserting everything is initiated + segment3dp.tools('check3dpfields') + + %Find suitable penradius + DATA.LevelSet.maxpenradius = min(11*[SET(NO).ResolutionX SET(NO).ResolutionY ... + SET(NO).SliceThickness+SET(NO).SliceGap]); + SET(NO).LevelSet.Pen.Radius = min(DATA.LevelSet.maxpenradius, SET(NO).LevelSet.Pen.Radius); + set(DATA.Handles.penradiusedit,'string',sprintf('%0.1g',SET(NO).LevelSet.Pen.Radius)); + + %Set edit boxes + segment3dp.tools('setpredefined'); + + %Scale axes + g = linspace(0,1,128)'; + DATA.LevelSet.colormap = [[g g g] ; ... + [ones(128,1) linspace(0,1,128)' zeros(128,1)]]; + image(reshape(flipud(DATA.LevelSet.colormap),[size(DATA.LevelSet.colormap,1) 1 3]),'parent',DATA.Handles.scaleaxes); + axis(DATA.Handles.scaleaxes,'off'); + cmap = gray(256); + image(reshape(flipud(cmap),[size(cmap,1) 1 3]),'parent',DATA.Handles.intensityscaleaxes); + axis(DATA.Handles.intensityscaleaxes,'off'); + drawfunctions('drawmapping'); + segment3dp.tools('updatesloperadiobuttons'); + drawfunctions('updatemapping'); + segment3dp.tools('updatemappingedit'); + segment3dp.tools('updateobjects'); + drawfunctions('drawintensitymapping'); + + for loop = 1:length(DATA.ViewPanels) + if ~isequal(DATA.ViewPanelsType{loop},'speedim') + drawfunctions('drawtext',loop); + end + end + + %Set current pen color + switch DATA.ViewPanelsType{DATA.CurrentPanel} + case 'trans3DP' + SET(DATA.ViewPanels(DATA.CurrentPanel)).LevelSet.Pen.Color = 'r'; + case 'sag3DP' + SET(DATA.ViewPanels(DATA.CurrentPanel)).LevelSet.Pen.Color = 'g'; + case 'cor3DP' + SET(DATA.ViewPanels(DATA.CurrentPanel)).LevelSet.Pen.Color = 'b'; + end + +else + %this draws and updates the panel image intersections. + drawfunctions('drawplaneintersections') +end +%When updating we only want to update the panels with content. These are +%DATA.ViewPanels>0 +nostodo = DATA.ViewPanels(DATA.ViewPanels>0); +panelstodo = find(nostodo); + +for i = panelstodo + + updatedrawlist(i) + DATA.ViewIM{i} = []; + + drawfunctions('drawpanel',i) + if ~specialview + if incr(i)~= 0 + % restore zoom + SET(nostodo(i)).NormalZoomState = []; + zoom(incr(i),i); + end + end + updatetextposition(i); + createfunctions('addcolorbar',i) + %view sliders + if ismember(DATA.ViewPanelsType{i},{'trans3DP','sag3DP','cor3DP','viewport','speedim'}) + + %Fix position + set(DATA.Handles.sliders(i),'units','normalized'); %needs to be set before, Matlab bug? + p = get(DATA.Handles.imageaxes(i),'Position'); + set(DATA.Handles.sliders(i),'Position',[p(1)+p(3)-0.01 p(2) 0.01 p(4)],'Visible','on'); + + %Fix min/max & value + [rmax,gmax,bmax] = segment3dp.tools('xyz2rgb',... + SET(NO).XSize,... + SET(NO).YSize,... + SET(NO).ZSize); + switch DATA.ViewPanelsType{i} + case 'trans3DP' + set(DATA.Handles.sliders(i),... + 'min',1,... + 'max',rmax,... + 'value',SET(NO).LevelSet.View.RSlice,... + 'SliderStep',... + [1/rmax 0.1],... + 'Callback',sprintf('segment3dp.tools(''rgbslider_Callback'',''r'',%d)',i)); + case 'sag3DP' + set(DATA.Handles.sliders(i),... + 'min',1,.... + 'max',gmax,... + 'SliderStep',[1/gmax 0.1],... + 'value',SET(NO).LevelSet.View.GSlice,... + 'Callback',sprintf('segment3dp.tools(''rgbslider_Callback'',''g'',%d)',i)); + case 'cor3DP' + set(DATA.Handles.sliders(i),... + 'min',1,... + 'max',bmax,... + 'SliderStep',[1/bmax 0.1],... + 'value',SET(NO).LevelSet.View.BSlice,... + 'Callback',sprintf('segment3dp.tools(''rgbslider_Callback'',''b'',%d)',i)); + case {'viewport','speedim'} + if segment3dp.isviewportalive && DATA.Handles.configiconholder.findindented('showcutplane') + set(DATA.Handles.sliders(i),'min',-50,'max',50,'visible','on','value',-SET(NO).LevelSet.View.CutPlaneOffset,'Callback',sprintf('segment3dp.tools(''cutplaneoffset_Callback'',%d)',i)); + end + end + + else + set(DATA.Handles.sliders(i),'Visible','off'); + end + +end + +%segment3dp.tools('updateoffsetslider'); + +%Remove slider from all others +allpanels = 1:length(DATA.Handles.sliders); +for i = setdiff(allpanels,panelstodo) + set(DATA.Handles.sliders(i),'Visible','off'); +end +if specialview + %functionality to restore same zoom state as before panel settings were + %changed + panelstodo = find(DATA.ViewPanels(DATA.ViewPanels>0)); + incr = zeros(length(panelstodo),1); + + for actpanel = panelstodo + no = DATA.ViewPanels(actpanel); + linkednos = SET(no).Linked; + if length(linkednos) > 1 + SET(linkednos(2:end)).NormalZoomState = []; + end + type = DATA.ViewPanelsType{actpanel}; + if any(contains({'one'},type)) + zoomstatecurrent = SET(no).NormalZoomState; + if ~isempty(zoomstatecurrent) + % compare current state to the original + % where original would be zoom state without zooming + zoomstateoriginal = getnewzoomstate(actpanel,no,false); + szxorig = zoomstateoriginal(2)-zoomstateoriginal(1); + szxcurrent = zoomstatecurrent(2)-zoomstatecurrent(1); + if ~isnan(szxorig) && ~isnan(szxcurrent) && ~isapproxequal(szxorig,szxcurrent) + % ratios not equal -> ther was zooming + f = szxcurrent/szxorig; + % recalculate zoom increment + incr(actpanel) = round((1-f)*7); + end + end + end + end + for i = panelstodo + if incr(i)~= 0 + % restore zoom + SET(nostodo(i)).NormalZoomState = []; + zoom(incr(i),i); + end + end +end +% end of restoring zoom +drawfunctions('drawselectedframe',DATA.CurrentPanel) +drawfunctions('drawselectedslice',DATA.CurrentPanel) +buttondownfunctions('updatebuttondowns') + +DATA.setviewbuttons(0); +segment('updatevolume'); +segment('updateflow'); +segment('updatemeasurement'); +DATA.updatetimebaraxes +%create thumbnails and draw frame around them +drawfunctions('drawthumbnails',isempty(DATA.DATASETPREVIEW)); +%profile report + +%--------------------- +function configaxes +%----------------------- +%configure imageaxes and boxaxes according to current config. +global DATA + +rows = DATA.ViewMatrix(1); +cols = DATA.ViewMatrix(2); + +left = DATA.GUISettings.LeftGapWidth; %0.12; +right = 1-DATA.GUISettings.RightGapWidth-0.02; %Based on that the report panel can never be more than 220. +bottom = DATA.GUISettings.BottomGapHeight; %0.013; +top = 1-DATA.GUISettings.TopGapHeight; +width = right-left; +height = top-bottom; + +%bottom = bottom+0.1; +%height = height-0.1; + +%Set the box axes position +DATA.Handles.boxaxes.Position = [left bottom width height]; + +%Set up the frame around all the panels +x = []; +y = []; +for rloop=1:(rows-1) + x = [x nan 0 1]; + y = [y nan 1/rows*rloop 1/rows*rloop]; +end + +for cloop=1:(cols-1) + x = [x nan 1/cols*cloop 1/cols*cloop]; + y = [y nan 0 1]; +end + +x = [x,[nan 0 1]]; +y = [y,[nan 0 0]]; +x = [x,[nan 0 1]]; +y = [y,[nan 1 1]]; +x = [x,[nan 0 0]]; +y = [y,[nan 0 1]]; +x = [x,[nan 1 1]]; +y = [y,[nan 0 1]]; + +DATA.Handles.box.XData = x; +DATA.Handles.box.YData = y; + +%Place all panels +counter = 1; +for rloop=(rows-1):-1:0 + for cloop=0:(cols-1) + DATA.Handles.imageaxes(counter).Position = [left+cloop*width/cols bottom+rloop*height/rows width/cols height/rows]; + counter = counter + 1; + end +end + +%nan all handles and axes not shown +drawfunctions('setxynan') + +%if viewport is up +if ~strcmp(DATA.CurrentTheme,'3dp') && ~isempty(DATA.LevelSet) && isfield(DATA.LevelSet,'ViewPort') && ~isempty(DATA.LevelSet.ViewPort) %&& DATA.Handles.configiconholder.findindented('view3d') + try + delete(DATA.LevelSet.ViewPort) + catch + end + DATA.LevelSet.ViewPort = []; +end + +%------------------------------ +function im = getgla(no) +%------------------------------ +global SET + +[x,y] = setglacenter(no); + +t0 = SET(no).CurrentTimeFrame; +z0 = SET(no).CurrentSlice; + +t = 1:SET(no).TSize; +z = 1:SET(no).ZSize; + +%Define image axes in xy plane and along z and t axis +xyline = [x;y;t0*ones(size(x));z0*ones(size(x))]; +zline = [SET(no).HLA.slice*ones(size(z));SET(no).VLA.slice*ones(size(z));t0*ones(size(z));z]; +tline = [SET(no).HLA.slice*ones(size(t));SET(no).VLA.slice*ones(size(t));t;z0*ones(size(t))]; + +X = meshgrid(xyline(1,:),zline(1,:),tline(1,:)); +Y = meshgrid(xyline(2,:),zline(2,:),tline(2,:)); +[~,~,T] = meshgrid(xyline(3,:),zline(3,:),tline(3,:)); +[~,Z] = meshgrid(xyline(4,:),zline(4,:),tline(4,:)); + +if SET(no).TSize == 1 + im = interpn(squeeze(SET(no).IM),X,Y,Z,'nearest'); +else + im = interpn(SET(no).IM,X,Y,T,Z,'nearest'); +end +%--------------------- +function orthoview(no) +%--------------------- +% Create orthogonal view for stack no and store necessary fields into SET +% struct +global SET NO +if nargin < 1 + no = NO; +end + +SET(no).HLA.slice = round(SET(no).XSize/2); +SET(no).HLA.maxslice = SET(no).XSize; +SET(no).HLA.ZoomState = []; + +SET(no).VLA.slice = round(SET(no).YSize/2); +SET(no).VLA.maxslice = SET(no).YSize; +SET(no).VLA.ZoomState = []; + +ang = 2*pi/8; +SET(no).GLA.angle = ang; +SET(no).GLA.slice = 0; +SET(no).GLA.ZoomState = []; + +setglacenter(no); + +%------------------------------ +function [x,y] = setglacenter(no) +%------------------------------ +global SET + +%Define coordinates of midpoint and find image edge +x0 = SET(no).HLA.slice; +y0 = SET(no).VLA.slice; +tlim = zeros(1,4); + +%Here should SET(no).ResolutionX and ResolutionY be introduced somehow +tlim(1) = SET(no).ResolutionX*(1-SET(no).HLA.slice)/sin(SET(no).GLA.angle); +tlim(2) = SET(no).ResolutionY*(1-SET(no).VLA.slice)/cos(SET(no).GLA.angle); +tlim(3) = SET(no).ResolutionX*(SET(no).XSize-SET(no).HLA.slice)/sin(SET(no).GLA.angle); +tlim(4) = SET(no).ResolutionY*(SET(no).YSize-SET(no).VLA.slice)/cos(SET(no).GLA.angle); +tlim = sort(tlim); +tmin = tlim(2); +tmax = tlim(3); + +%Define extension +res = SET(no).ResolutionY*cos(SET(no).GLA.angle)+SET(no).ResolutionX*abs(sin(SET(no).GLA.angle)); + +if cos(SET(no).GLA.angle) >= 0 + x = x0 + sin(SET(no).GLA.angle)*(tmin:res:tmax)/SET(no).ResolutionX; %linspace(tmin,tmax,sz); + y = y0 + cos(SET(no).GLA.angle)*(tmin:res:tmax)/SET(no).ResolutionY; %linspace(tmin,tmax,sz); +else + x = x0 + sin(SET(no).GLA.angle)*(tmax:-res:tmin)/SET(no).ResolutionX; %linspace(tmin,tmax,sz); + y = y0 + cos(SET(no).GLA.angle)*(tmax:-res:tmin)/SET(no).ResolutionY; +end + +SET(no).GLA.x0 = x(1); +SET(no).GLA.y0 = y(1); + +%------------------------------------------------------ +function [measure,slice] = getmeasurecoords(panel) +%------------------------------------------------------ +%Get coordinates of measurements with respect to the current view +global DATA SET +no = DATA.ViewPanels(panel); +type = DATA.ViewPanelsType{panel}; + +switch type + case 'hla' + measure = struct( ... + 'X',{SET(no).Measure.Z}, ... + 'Y',{SET(no).Measure.Y}, ... + 'Z',{SET(no).Measure.X}, ... + 'T',{SET(no).Measure.T}); + slice = SET(no).HLA.slice; + case 'vla' + measure = struct( ... + 'X',{SET(no).Measure.Z}, ... + 'Y',{SET(no).Measure.X}, ... + 'Z',{SET(no).Measure.Y}, ... + 'T',{SET(no).Measure.T}); + slice = SET(no).VLA.slice; + case 'gla' + ang = SET(no).GLA.angle; + res = SET(no).ResolutionY*cos(ang)+SET(no).ResolutionX*abs(sin(ang)); + measure = struct( ... + 'X',{SET(no).Measure.Z}, ... + 'Y',cellfun(@(y,x)1/res*(SET(no).ResolutionY*(y-SET(no).GLA.y0)*cos(ang) + ... + SET(no).ResolutionX*(x-SET(no).GLA.x0)*sin(ang)), ... + {SET(no).Measure.Y},{SET(no).Measure.X},'UniformOutput',false), ... + 'Z',cellfun(@(y,x)1/res*(SET(no).ResolutionY*(y-SET(no).GLA.y0)*-sin(ang) + ... + SET(no).ResolutionX*(x-SET(no).GLA.x0)*cos(ang)), ... + {SET(no).Measure.Y},{SET(no).Measure.X},'UniformOutput',false), ... + 'T',{SET(no).Measure.T}); + slice = 0; + otherwise + measure = struct( ... + 'X',{SET(no).Measure.X}, ... + 'Y',{SET(no).Measure.Y}, ... + 'Z',{SET(no).Measure.Z}, ... + 'T',{SET(no).Measure.T}); + slice = SET(no).CurrentSlice; +end + +%----------------------------------------- +function switchtimeframe(incr,synchronize) %#ok +%----------------------------------------- +global DATA SET + +panel = DATA.CurrentPanel; +no = DATA.ViewPanels(panel); +tools('connectinterpolation',no,{'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}); +if nargin == 1 + synchronize = 0; +end +if SET(no).TSize == 1 + return +end +if abs(incr) > SET(no).TSize + signincr = sign(incr); + incr = signincr*mod(abs(incr),SET(no).TSize); +end +SET(no).CurrentTimeFrame = SET(no).CurrentTimeFrame+incr; +if SET(no).CurrentTimeFrame>SET(no).TSize + tfdiff = SET(no).CurrentTimeFrame-SET(no).TSize; + SET(no).CurrentTimeFrame = tfdiff; +end + +if SET(no).CurrentTimeFrame<1 + SET(no).CurrentTimeFrame = SET(no).TSize+SET(no).CurrentTimeFrame; +end + +%Calculate percentage +percent = (SET(no).CurrentTimeFrame-1)/(SET(no).TSize-1); + +if not(contains(DATA.ProgramName,'3DP')) && (findindented(DATA.Handles.hideiconholder,'synchronize')||synchronize) + panels = find(DATA.ViewPanels>0); + nos = unique(DATA.ViewPanels(panels)); +else + nos = no; + linkednos = SET(nos).Linked; + if linkednos > 1 + % look if the linked no is shown + panels = find(ismember(DATA.ViewPanels, linkednos)); + else + panels = panel; + end +end +% change timeframe also in linked nos, even if they are not shown +linkednos = cell2mat({SET(nos).Linked}); +nos = unique([nos,linkednos]); + +%Loop over all image stacks to update time. +for loop=nos + SET(loop).CurrentTimeFrame = min(max(1,1+round(percent*(SET(loop).TSize-1))),SET(loop).TSize); +end + +for p = panels + viewfunctions('updatedrawlist',p) + drawfunctions('drawpanel',p) +end + +%also update the timebars! +viewfunctions('updatetimebars'); + +%--------------------- +function updatetimebars(synchronize) %#ok +%----------------------- +%updates all timebars +global DATA SET NO + +no = NO; + +if nargin == 0 + if not(contains(DATA.ProgramName,'3DP')) && findindented(DATA.Handles.hideiconholder,'synchronize') + synchronize = 1; + else + synchronize = 0; + end +end + + +if ~isempty(DATA.LVNO)|| strcmp(DATA.ProgramName,'Segment') + if strcmp(DATA.ProgramName,'Segment') + t = SET(no).TimeVector*1000; + else + t = SET(DATA.LVNO(1)).TimeVector*1000; + end + + if any(no == DATA.LVNO) || strcmp(DATA.ProgramName,'Segment') || (synchronize && any(DATA.ViewPanels == DATA.LVNO)) + + if strcmp(DATA.ProgramName,'Segment') + set(DATA.Handles.timebarlv,'xdata',... + t(SET(no).CurrentTimeFrame)*[1 1]) + else + set(DATA.Handles.timebarlv,'xdata',... + t(SET(DATA.LVNO(1)).CurrentTimeFrame)*[1 1]) + end + + end +end + + + + +if ~isempty(DATA.FlowNO) + if strcmp(DATA.ProgramName,'Segment') + t = SET(no).TimeVector*1000; + else + t = SET(DATA.FlowNO(1)).TimeVector*1000; + end + + if no == DATA.FlowNO || strcmp(DATA.ProgramName,'Segment') || (synchronize && any(DATA.ViewPanels == DATA.FlowNO)) + if strcmp(DATA.ProgramName,'Segment') + DATA.Handles.timebarflow.XData = t(SET(no).CurrentTimeFrame)*[1 1]; + else + DATA.Handles.timebarflow.XData = t(SET(DATA.FlowNO).CurrentTimeFrame)*[1 1]; + end + end +end + +t = SET(no).TimeVector*1000; +set(DATA.Handles.timebar,'xdata',... + t(SET(no).CurrentTimeFrame)*[1 1]); + +%--------------------- +function selectallslices %#ok +%----------------------- +%Selects all slices in panel +global DATA SET NO +slices = slicesinpanel(DATA.CurrentPanel); + +SET(NO).StartSlice = slices(1); +SET(NO).EndSlice= slices(end); +SET(NO).CurrentSlice= slices(end); + +drawfunctions('drawselectedslice',DATA.CurrentPanel); +drawfunctions('drawtext',DATA.CurrentPanel); + +%--------------------- +function unselectallslices %#ok +%----------------------- +%Unselects all slices in panel +global DATA SET NO +SET(NO).StartSlice = []; +SET(NO).EndSlice= []; +drawfunctions('drawselectedslice',DATA.CurrentPanel); +drawfunctions('drawtext',DATA.CurrentPanel); + +%--------------------- +function viewallimagestacks(viewpaneltype) %#ok +%----------------------- +%roll outs all image stacks (up to 6) into panels in one view mode. +global SET DATA + +N = length(SET); +switch N + case 1 + rows = 1; + cols = 1; + case 2 + rows = 1; + cols = 2; + case 3 + rows = 1; + cols = 3; + case 4 + rows = 2; + cols = 2; + otherwise%case {5,6} + rows = 2; + cols = 3; +end + +nos = 1:min(N,6); +if any(ismember(DATA.ViewPanelsType,{'orth','hla','gla','vla'})) + % reset orthogonal view to one panel view to avoid crashing + setview(1,1); +end +if nargin==0 + setview(rows,cols,nos) +else + vptcell = cell(size(nos)); + [vptcell{:}] = deal(viewpaneltype); + setview(rows,cols,nos,vptcell) +end +%--------------------- +function fastswitchslice(sliceincr,synchronize) %#ok +%----------------------- +%This is a first attempt at a fast slice toggling using a first render with +%only one timeframe. The design is that a timer is initiated + +global DATA SET +persistent storetimer +if nargin == 1 + synchronize = 0; +end + +panel = DATA.CurrentPanel; +scale = getscale(panel); +no = DATA.ViewPanels(panel); +SET(no).CurrentSlice = SET(no).CurrentSlice+sliceincr; + +if SET(no).CurrentSlice <= 0 + SET(no).CurrentSlice = 1; +end + +if SET(no).CurrentSlice >SET(no).ZSize + SET(no).CurrentSlice = SET(no).ZSize; +end + +if ~isempty(storetimer) + clear('storetimer') +end + +storetimer=timer('ExecutionMode','singleShot',... + 'TimerFcn',sprintf('viewfunctions(''switchslice'',%d,%d)',0,synchronize), ... + 'StartDelay',1); +outim = SET(no).IM(:,:,SET(no).CurrentTimeFrame,SET(no).CurrentSlice); +im = calcfunctions('remapuint8viewim',outim,no); + +DATA.Handles.imagehandles(panel).CData = imresize(im,scale); + +for i = 2:length(DATA.drawlist{panel}) + eval(DATA.drawlist{panel}{i}) +end + +start(storetimer) + +%--------------------- +function switchslice(sliceincr,synchronize) %#ok +%----------------------- +global DATA SET + +panel = DATA.CurrentPanel; +no = DATA.ViewPanels(panel); +slice = SET(no).CurrentSlice+sliceincr; +tools('connectinterpolation',no,{'EndoInterp','EpiInterp','RVEndoInterp','RVEpiInterp'}) +if nargin == 1 + synchronize = 0; +end + +%If one then we need to re-generate viewpanels +if strcmp(DATA.ViewPanelsType{panel},'one') || strcmp(DATA.ViewPanelsType{panel},'orth') + DATA.ViewIM{panel} = []; +end + +if slice > SET(no).ZSize + slice = SET(no).ZSize; +end + +if slice < 1 + slice = 1; +end + +SET(no).CurrentSlice = slice; +SET(no).StartSlice = slice; + +%segment('updatevolume') +SET(no).EndSlice = slice; + +if not(contains(DATA.ProgramName,'3DP')) && (findindented(DATA.Handles.hideiconholder,'synchronize') || synchronize) +% pno = segment('updateparallelsets',no); +% panels = find(ismember(DATA.ViewPanels,[pno no])); + panels = find(DATA.ViewPanels>0); + nos = unique(DATA.ViewPanels(panels)); +else + nos = no; + linkednos = SET(nos).Linked; + if linkednos > 1 + % look if the linked no is shown + panels = find(ismember(DATA.ViewPanels, linkednos)); + else + panels = panel; + end +end +% change timeframe also in linked nos, even if they are not shown +linkednos = cell2mat({SET(nos).Linked}); +nos = unique([nos,linkednos]); +%update Currentslice in all linked nos +invisiblenos = setdiff(nos,DATA.ViewPanels); +if not(isempty(invisiblenos)) + for n = invisiblenos + thisslice = findcorrespondingslice(slice,no,n); + if ~isempty(thisslice) && ~isnan(thisslice) && thisslice > 0 && thisslice <= SET(n).ZSize + SET(n).CurrentSlice = thisslice; + SET(n).StartSlice = thisslice; + SET(n).EndSlice = thisslice; + end + end +end + +%Loop over all panels to update slice +for loop = panels + + thisno = DATA.ViewPanels(loop); + + if ~isequal(no,thisno) + thisslice = findcorrespondingslice(slice,no,thisno); + + if (~isempty(thisslice)) && (~isequal(thisslice,SET(thisno).CurrentSlice)) + SET(thisno).CurrentSlice = thisslice; + SET(thisno).StartSlice = thisslice; + SET(thisno).EndSlice = thisslice; + end + end + %Check if need to recompute the image + if strcmp(DATA.ViewPanelsType{loop},'one') || strcmp(DATA.ViewPanelsType{loop},'orth') + DATA.ViewIM{loop} = []; + end +end + +%this draws and updates the panel image intersections. +drawfunctions('drawplaneintersections') + +%Do graphical update. If in montage view this corresponds to changing the +%highlighted frame. If other then we need to update viewim and redraw the +%panel. + +for p = panels + viewfunctions('updatedrawlist',p) +end + +for p = panels + if any(strcmp(DATA.ViewPanelsType{p},{'montage','montagerow'})) + drawfunctions('drawselectedslice',p) + drawfunctions('drawtext',p) + elseif strcmp(DATA.ViewPanelsType{p},'montagesegmented') + drawfunctions('drawselectedslice',p) + drawfunctions('drawtext',p) + drawfunctions('drawpanel',p) + else + %making the viewim empty triggers generation of a new viewim + drawfunctions('drawpanel',p) + end +end + +%---------------------------------------------------------------- +function thisslice = findcorrespondingslice(refslice,refno,thisno) +%---------------------------------------------------------------- +%Find correspondingslice given a refslice in a refno for the stack thisno + +global SET + +%Compute zaxis for ref +v1ref = SET(refno).ImageOrientation(1:3); +v2ref = SET(refno).ImageOrientation(4:6); +zref = cross(v1ref,v2ref); + +%Compute zaxis for this +v1this = SET(thisno).ImageOrientation(1:3); +v2this = SET(thisno).ImageOrientation(4:6); +zthis = cross(v1this,v2this); + +%Compare them +angle = acos(abs(sum(zref.*zthis)))/pi*180; %angle between them in degrees + +if angle<20 + pos = calcfunctions('xyz2rlapfh',refno,SET(refno).XSize/2,SET(refno).YSize/2,refslice); + xyz = calcfunctions('rlapfh2xyz',thisno,pos(1),pos(2),pos(3)); + + thisslice = round(xyz(3)); + + if thisslice > SET(thisno).ZSize + thisslice = []; + end + if thisslice < 1 + thisslice = []; + end + +else + thisslice = []; + return +end + +%---------------------------------- +function zoomstate = updateglazoomstate(no,ysz) +%---------------------------------- +%This function helps with updating the zoom for the gla view when in +%orthoview mode. +global SET +xzoomsz = max(SET(no).XSize,SET(no).YSize); +repos = (ysz-xzoomsz)/2; +zoomstate = 0.5+[repos+[0;xzoomsz];0;SET(no).ZSize]; + +%--------------------------------------- +function viewhideallspecial_Callback(varargin) %#ok +%--------------------------------------- +%all hide buttons +global DATA +stateandicon = iconson('hideall'); +state = stateandicon{1}; +hidecell = {'hideplus','hidemar','hidescar','hidescarextent','hidescarmanual',... 'hidepins', + 'hideintersections','hideothercontour','hideinterp','hidelv','hiderv','hideroi','hidemeasure','hidepoint','hidetext'};%,'colorbar'}; +stateandicon = iconson(hidecell); +availableicons = find(cellfun(@(x) isa(x,'myicon'),stateandicon(:,2)))'; +if state + DATA.LastHideIconState = stateandicon; + for i = availableicons + icon = stateandicon{i,2}; + icon.cdataDisplay = icon.cdataIndent; + icon.isindented = 1; + end +else + if ~isempty(DATA.LastHideIconState) + stateandicon = DATA.LastHideIconState; + for i = availableicons + icon = stateandicon{i,2}; + if stateandicon{i,1} + icon.cdataDisplay = icon.cdataIndent; + icon.isindented = 1; + else + icon.cdataDisplay = icon.cdata; + icon.isindented = 0; + end + end + DATA.LastHideIconState = []; + end +end +viewfunctions('updatevisibility'); +DATA.Handles.configiconholder.render; +%--------------------------------------- +function viewhideall_Callback(varargin) %#ok +%--------------------------------------- +%all hide buttons +global DATA +stateandicon=iconson('hideall'); +state=stateandicon{1}; +hidecell={'hideplus','hidemar','hidescar','hidescarextent','hidescarmanual',... 'hidepins', + 'hideintersections','hideothercontour','hideinterp','hidelv','hiderv','hideroi','hidemeasure','hidepoint','hidetext'};%,'colorbar'}; +stateandicon = iconson(hidecell); +availableicons = find(cellfun(@(x) isa(x,'myicon'),stateandicon(:,2)))'; +if state + DATA.LastHideIconState = stateandicon; + for i=availableicons + icon = stateandicon{i,2}; + icon.cdataDisplay=icon.cdataIndent; + icon.isindented=1; + end +else + for i=availableicons + icon = stateandicon{i,2}; + icon.cdataDisplay=icon.cdata; + icon.isindented=0; + end +end +viewfunctions('updatevisibility'); +DATA.Handles.configiconholder.render; + +%------------------------------------------- +function state = iconson(name) +%------------------------------------------ +%if given name of button return state if run with no input returns +%states of all buttons. if given cell with multiple button return icons +%in order of request. +global DATA + +state=0; +if not(contains(DATA.ProgramName,'3D')) + icons=[DATA.Handles.permanenticonholder.iconCell{:},DATA.Icons.lviconcell{:},DATA.Icons.rviconcell{:},DATA.Icons.roiflowiconcell{:},DATA.Icons.viabilityiconcell{:},... + DATA.Icons.analysisiconcell{:}, DATA.Icons.imageiconcell{:},DATA.Icons.hidecell{:}]; +else + icons=[DATA.Icons.lviconcell{:},DATA.Icons.printiconcell{:},DATA.Icons.imageiconcell{:}]; +end +N=length(icons); + +if nargin==1 + %return icon state + if ~iscell(name) + ind=find(strcmp(name,{icons.name})); + if length(ind)>1 + ind=ind(1); + end + + if isempty(ind) + state={0,nan}; + else + state={icons(ind).isindented,icons(ind)}; + end + + else + n=length(name); + state=cell(n,2); + %Get all icons and states for names in cell + counter=1; + indlist=zeros(1,n); + for i=1:n + ind=find(strcmp(name(i),{icons.name})); + + if isempty(ind) + ind=nan; + end + + if length(ind)>1 + ind=ind(1); + end + + indlist(i)=ind; + end + + for i=1:n + if isnan(indlist(i)) + state{i,1} = 0; + state{i,2} = nan; + else + state{i,1} = icons(indlist(i)).isindented; + state{i,2} = icons(indlist(i)); + end + end + end +else + state=cell(N,2); + for i=1:N + state{i,1} = icons{i}.name; + state{i,2} = icons{i}.isindented; + end +end + + +%------------------------- +function allhidden +%---------------------- +%show/hide all overlayes in the image view + +global DATA +stateandicon=iconson('hideall'); +hideallstate=stateandicon{1}; +hideallicon=stateandicon{2}; + +if hideallstate + hidecell={'hideplus','hidemar','hidescar','hidescarextent','hidescarmanual',...'hidepins', + 'hideintersections','hideothercontour','hideinterp','hidelv','hiderv','hideroi','hidemeasure','hidepoint','hidetext'};%,'colorbar'}; + stateandicon = iconson(hidecell); + availableicons = cellfun(@(x) isa(x,'myicon'),stateandicon(:,2)); + state=[stateandicon{availableicons,1}]; + + if any(state==0) + hideallicon.undent + if contains(DATA.ProgramName,'3D') + DATA.Handles.configiconholder.render; + else + DATA.Handles.permanenticonholder.render; + end + end +end + +%-------------------------- +function hide(names,states) %#ok +%-------------------------- +%Gets and sets icons with specific name in the different iconholders even those not showing at the moment according to state +global DATA +stateandicon = viewfunctions('iconson',names); + +for i =1:size(stateandicon,1) + if isprop(stateandicon{i,2},'isindented') + stateandicon{i,2}.isindented = states(i); + end +end + +DATA.Handles.configiconholder.render; +% viewfunctions('setview') +viewfunctions('updatevisibility'); + +%--------------------------------------- +function hide_Callback(varargin) %#ok +%--------------------------------------- +%Toggle visibility for the imageoverlay +viewfunctions('updatevisibility'); +allhidden + +%--------------------------------- +function viewhidecolorbar_Callback %#ok +%--------------------------------- +%Toggle visibility of colorbar +global DATA + +stateandicon=iconson('colorbar'); +state=stateandicon{1}; +%stateandicon{2}.isindented=state; +if ~state + DATA.GUISettings.ShowColorbar = false; +else + DATA.GUISettings.ShowColorbar = true; +end +%do full refresh with colorbar +for p = find(DATA.ViewPanels) + createfunctions('addcolorbar',p) +end + +allhidden + +%----------------------------------- +function viewhidepap_Callback %#ok +%--------------------------------- +%Toggle visibility of papillary overlay. This overlay is +%incorporated in the viewim so resetting them and assuring it doesnt +%trigger when button is indented + +global DATA +viewfunctions('updatevisibility') +DATA.ViewIM = cell(size(DATA.ViewIM)); +for p = find(DATA.ViewPanels) + drawfunctions('drawpanel',p); +end +allhidden +%-------------------------- +function viewhidemanualinteraction_Callback %#ok +%-------------------------- +%toogle visibility of manual interaction of Scar/MaR. This overlay is +%incorporated in the viewim so resetting them and assuring it doesnt +%trigger when button is indented. +global DATA + +viewfunctions('updatevisibility') +DATA.ViewIM = cell(size(DATA.ViewIM)); +for p = find(DATA.ViewPanels) + drawfunctions('drawpanel',p); +end +allhidden + +%-------------------------------- +function viewinterp_Callback(val) %#ok +%-------------------------------- +%Update if the view interpolated view is selected / unselected + +global DATA +if nargin < 1 + val = ~DATA.Pref.ViewInterpolated; +end +DATA.Pref.ViewInterpolated = val; +DATA.ViewIM = cell(size(DATA.ViewIM)); %This clear ViewIM and it is reconstructed +for p = find(DATA.ViewPanels) + drawfunctions('drawpanel',p); +end +drawfunctions('drawplaneintersections'); + +%----------------------------------- +function viewportviewfrom(type) %#ok +%----------------------------------- +%Update view direction in viewport depending on direction + +global DATA SET NO + +%Get object handle +viewport = DATA.LevelSet.ViewPort; + +imageorientation = SET(NO).ImageOrientation; +imageorientation = [1 0 0 0 1 0]; + +zdir = cross(... + imageorientation(1:3),... + imageorientation(4:6)); + +Rxyz2rlapfh = [imageorientation(4:6)' imageorientation(1:3)' -zdir']; + +Rrlapfh2xyz = inv(Rxyz2rlapfh); + +%Get camera position +pos = viewport.getcameraposition; + +%Check distance to center (origo) for camera +r = sqrt(sum(pos.*pos)); + +%Define in rlapfh coordinates +switch type + case 'transversal' + posrlapfh = [0 r 0]; + upvrlapfh = [0 0 1]; + case 'sagittal' + posrlapfh = [-r 0 0]; + upvrlapfh = [0 0 1]; + case 'coronal' + posrlapfh = [0 0 r]; + upvrlapfh = [-1 0 0]; +end + +%Convert to xyz coordinates +posxyz = Rrlapfh2xyz*(posrlapfh'); +upvxyz = Rrlapfh2xyz*(upvrlapfh'); + +%Update camera position +viewport.setcamera(posxyz,upvxyz); + +%----------------------------------- +function updatelinewidth %#ok +%----------------------------------- +global DATA + +linewidth = DATA.Pref.LineWidth; +if ~isempty(linewidth) + colortypes = 'cgbrwkym'; + type = {'Endo','Epi','RVEndo','RVEpi'}; + for panel = 1: length(DATA.ViewPanels) + DATA.Handles.roicurrent(panel).LineWidth = linewidth + 1; + DATA.Handles.scarcontour(panel).LineWidth = linewidth; + DATA.Handles.marcontour(panel).LineWidth = linewidth; + for loop = 1: length(type) + DATA.Handles.([lower(type{loop}),'contour'])(panel).LineWidth = linewidth; + end + for cind = 1:length(colortypes) + DATA.Handles.([colortypes(cind),'roi'])(panel).LineWidth = linewidth; + end + end +end + +%------------------------------------ +function updateintersectionmarkersize +%------------------------------------ +%update marker size for intersection points + +global DATA + +%update marker size for all intersection +for panel = 1:size(DATA.Handles.endocontourintersection,2) + set(DATA.Handles.endocontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.endocontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.epicontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.epicontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.rvendocontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.rvendocontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.rvepicontourintersection(panel),'markersize',DATA.Pref.MarkerSize); + set(DATA.Handles.rvepicontourintersection(panel),'markersize',DATA.Pref.MarkerSize); +end + +if DATA.Pref.BlackWhite + set(DATA.Handles.endocontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.endocontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.epicontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.epicontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.rvendocontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.rvendocontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.rvepicontourintersection(panel),'color',[1 1 1]); + set(DATA.Handles.rvepicontourintersection(panel),'color',[1 1 1]); +end + +%update display +for panel = 1: length(DATA.ViewPanels) + drawfunctions('drawintersections',panel) +end + +%------------------------------------------------------ +function z = reshape2layout(im,panel,outsideelement) +%------------------------------------------------------ +%Convert a 3D array to an layout:ed image with cols, and rows +global DATA SET +no = DATA.ViewPanels(panel); + +if nargin < 3 + outsideelement = 0; +end +z = repmat(im(1).*outsideelement,DATA.ViewPanelsMatrix{panel}(2)*SET(no).XSize,DATA.ViewPanelsMatrix{panel}(1)*SET(no).YSize); +loop=1; +for slice=1:SET(no).ZSize + c = 1+mod(loop-1,DATA.ViewPanelsMatrix{panel}(1)); + r = ceil(loop/DATA.ViewPanelsMatrix{panel}(1)); + z(... + (1+(r-1)*SET(no).XSize):(r*SET(no).XSize),... + (1+(c-1)*SET(no).YSize):(c*SET(no).YSize)) = im(:,:,slice); + loop=loop+1; +end + +%------------------------------------------------------ +function updateflowresultstack %#ok +%------------------------------------------------------ +%check if flow stack in result panel should be updated + +global SET NO DATA + +[~,~,flowno] = findfunctions('findno'); +% need to switch stack only if there is flow at all && current stack is a +% flowstack && current stack is not already presented in result panel +if ~isempty(flowno) && any(flowno == NO) && ~isempty(DATA.FlowNO) && not(any(DATA.FlowNO == SET(NO).Linked)) + % get parent stack + if ~isempty(SET(NO).Flow) && isfield(SET(NO).Flow,'MagnitudeNo') + magno = SET(NO).Flow.MagnitudeNo; + if SET(magno).RoiN > 0 + DATA.FlowNO = magno; + DATA.FlowROI = SET(magno).RoiCurrent; + DATA.updateflow; + end + end +end + +%--------------------------------------- +function updatetoolhidestate(currenttool) %#ok +%--------------------------------------- +%function to update hide icons depending on the choosen tool, callback come +%from updatebuttondowns and pen_buttondown +%This function helps to avoid that user draw with pen but do not see the +%results +global DATA +if ~DATA.LastToolHideState + switch currenttool + case {'Endo','Epi'} + iconname = 'hidelv'; + case {'RVEndo','RVEpi'} + iconname = 'hiderv'; + case {'Roi','RoiPut'} + iconname = 'hideroi'; + case {'Scar','MO'} + iconname = 'hidescar'; + case 'MaR' + iconname = 'hidemar'; + otherwise + return + end + stateandicon = iconson(iconname); + if stateandicon{1} + DATA.Handles.configiconholder.undent(iconname,1) + end +end \ No newline at end of file diff --git a/source/whichstack.fig b/source/whichstack.fig index 38bd120..efe679d 100644 Binary files a/source/whichstack.fig and b/source/whichstack.fig differ diff --git a/source/wizardsetup.fig b/source/wizardsetup.fig new file mode 100644 index 0000000..808cf23 Binary files /dev/null and b/source/wizardsetup.fig differ diff --git a/source/wizardsetup.p b/source/wizardsetup.p new file mode 100644 index 0000000..00512f0 Binary files /dev/null and b/source/wizardsetup.p differ diff --git a/source/yesno.fig b/source/yesno.fig index b3fd47d..b8bf41e 100644 Binary files a/source/yesno.fig and b/source/yesno.fig differ diff --git a/source/yesno.m b/source/yesno.m index 34f2927..384499b 100644 --- a/source/yesno.m +++ b/source/yesno.m @@ -6,13 +6,28 @@ %YESNO(STRI,[],FIGHANDLE) % Same as above, but fighandle indicates alignment. % -%See also MYFAILED, MYWARNING, MYWAITBARSTART, MYMSGBOX. +% If DATA.Silent then message is just displayed in the console +% and exectution continues as if user had pressed ok. +% +%See also MYFAILED, MYWARNING, MYWAITBARSTART, MYMSGBOX, MYINPUTSTRUCT. %Einar Heiberg global DATA -persistent state +persistent state + +%If DATA.Silent then we can assume that user answers yes, which is the +%default. +try + if DATA.Silent + disp(sprintf('Yesno: %s : Yes',s)); %#ok + result = true; + return; + end +catch + %do nothing as error here depends on DATA not initialized +end s = translation.dictionary(s); @@ -23,66 +38,66 @@ keystroke = popfrombuffer('KeyStroke'); if ~isempty(keystroke) switch keystroke - case 'yes' + case 'yes' result = true; - mydisp(dprintf('yesno: %s. Yes',s)); + disp(sprintf('yesno: %s. Yes',s)); %#ok if ~isempty(DATA) && DATA.RecordMacro macro_helper('put','pushtobuffer(''KeyStroke'',''yes''); %yes in yesno'); macro_helper('switchorder'); %We need to store data in buffer before the callback - end; + end return; case 'no' result = false; - mydisp(dprintf('yesno: %s. No',s)); + disp(sprintf('yesno: %s. No',s)); %#ok if ~isempty(DATA) && DATA.RecordMacro macro_helper('put','pushtobuffer(''KeyStroke'',''no''); %no in yesno'); macro_helper('switchorder'); %We need to store data in buffer before the callback - end; + end return; otherwise - mydisp(dprintf('Yesno got:%s',keystroke)); + disp(sprintf('Yesno got:%s',keystroke)); %#ok error('Expected either ''yes'' or ''no'', got %s.',keystroke); - end; + end else if nargin==3 handles = initgui(s,fighandle); else handles = initgui(s); - end; - end; + end + end uiwait(handles.fig); else if isa(DATA, 'maingui') && DATA.RecordMacro recordmacro = DATA.RecordMacro; else recordmacro = false; - end; + end switch arg case 'yes' state = true; if recordmacro macro_helper('put','pushtobuffer(''KeyStroke'',''yes''); %yes in yesno'); macro_helper('switchorder'); %We need to store data in buffer before the callback - end; + end mydisp('yes'); case 'no' state = false; if recordmacro macro_helper('put','pushtobuffer(''KeyStroke'',''no''); %no in yesno'); macro_helper('switchorder'); %We need to store data in buffer before the callback - end; - mydisp('no'); + end + mydisp('no'); case 'yeskeypressed' yeskeypressed(s,arg); case 'nokeypressed' nokeypressed(s,arg); case 'return' state = false; - end; + end uiresume(s); close(s); -end; +end result = state; flushlog; @@ -91,18 +106,23 @@ function handles = initgui(s,fighandle) %-------------------------------------- %Init the GUI +global DATA + +fig = openfig('yesno.fig','invisible','reuse'); +try + set(fig,'Color',DATA.GUISettings.BackgroundColor); +catch + set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); +end -fig = openfig('yesno.fig','reuse'); -translation.translatealllabels(fig); -set(fig,'visible','off');%dlgbox not visble until it is horisontally aligned -set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); +setupicon(fig); %set up Segment icon %Horisontal alignment if nargin>1 - myadjust(fig,fighandle); + myadjust(fig,fighandle); else myadjust(fig); -end; +end %Extract handles handles = guihandles(fig); @@ -114,29 +134,61 @@ if numlinestopad>0 stri = [repmat({''},numlinestopad,1);s]; else -end; +end -set(handles.questiontext,'String',stri); +try + set(handles.questiontext,'String',stri,'BackgroundColor',DATA.GUISettings.BackgroundColor,... + 'ForegroundColor',DATA.GUISettings.ForegroundColor,'FontSize',16); +catch + set(handles.questiontext,'String',stri); +end mydisp(s); try myalign(handles.fig,fighandle); %Align horisontally catch %#ok -end; -set(fig,'visible','on');%dlgbox not visble until it is horisontally aligned +end +set(fig,'visible','on');%dlgbox not visble until it is horisontally aligned %Display question image -load('dialogicons.mat','questIconData','questIconMap'); -% questIconMap(256,:)=get(handles.fig,'color'); -image(questIconData,'parent',handles.imageaxes); +try + switch DATA.GUISettings.BackgroundColor(1) + case 0.2118 + load('dialogiconsblue.mat','questIconDataBlue','questIconMap'); + image(questIconDataBlue,'parent',handles.imageaxes); + case 0 + load('dialogiconsblack.mat','questIconDataBlack','questIconMap'); + image(questIconDataBlack,'parent',handles.imageaxes); + otherwise + load('dialogicons.mat','questIconData','questIconMap'); + % questIconMap(256,:)=get(handles.fig,'color'); + image(questIconData,'parent',handles.imageaxes); + end +catch + load('dialogicons.mat','questIconData','questIconMap'); + % questIconMap(256,:)=get(handles.fig,'color'); + image(questIconData,'parent',handles.imageaxes); +end colormap(handles.imageaxes,questIconMap); axis(handles.imageaxes,'off'); +set(handles.yespushbutton,'String',dprintf('Yes')); +set(handles.nopushbutton,'String',dprintf('No')); +handles.fig.Name = dprintf('Are you sure?'); %Add keypress callback set(handles.fig,'keypressfcn',@keypressed); -set(handles.yespushbutton','keypressfcn',@yeskeypressed); -set(handles.nopushbutton','keypressfcn',@nokeypressed); +try + set(handles.yespushbutton','keypressfcn',@yeskeypressed,'BackgroundColor',... + DATA.GUISettings.BackgroundColor,'ForegroundColor',DATA.GUISettings.ForegroundColor); +catch + set(handles.yespushbutton','keypressfcn',@yeskeypressed,'FontSize',12); +end +try set(handles.nopushbutton','keypressfcn',@nokeypressed,'BackgroundColor',... + DATA.GUISettings.BackgroundColor,'ForegroundColor',DATA.GUISettings.ForegroundColor); +catch + set(handles.nopushbutton','keypressfcn',@nokeypressed,'FontSize',12); +end %------------------------------- function keypressed(fignum,evnt) @@ -150,7 +202,7 @@ function keypressed(fignum,evnt) yesno(fignum,'yes'); case {'n','N'} yesno(fignum,'no'); -end; +end %---------------------------------- function yeskeypressed(fignum,evnt) %#ok @@ -161,8 +213,8 @@ function yeskeypressed(fignum,evnt) %#ok yesno(gcbf,'yes'); otherwise yesno(gcbf,'no'); -end; - +end + %---------------------------------- function nokeypressed(fignum,evnt) %#ok %---------------------------------- @@ -173,4 +225,4 @@ function nokeypressed(fignum,evnt) %#ok yesno(gcbf,'yes'); otherwise yesno(gcbf,'no'); -end; \ No newline at end of file +end diff --git a/source/yesnodialogwithimage.m b/source/yesnodialogwithimage.m new file mode 100644 index 0000000..6b4f6ac --- /dev/null +++ b/source/yesnodialogwithimage.m @@ -0,0 +1,120 @@ +function usersanswer = yesnodialogwithimage(imagedata,txtmessage) +% function to show a user dialog that shows an image and two buttons with +% options "YES,continue" and "NO, return" +global DATA +% get current screensize in pixels +set(0,'units','pixels') +screensizeinpix = get(0,'screensize'); +usersanswer = false; +% calculate figure position +figwidth = 300; +figheight = 500; +figstartx = floor(screensizeinpix(3)-figwidth)/2; +figstarty = floor(screensizeinpix(4)-figheight)/2; +% create an invisible figure +fig = figure(... + ...'Visible', 'off',... + 'Name',dprintf('Warning'), ... + 'MenuBar','none',... + 'Resize', 'off',... + 'keypressfcn',@keypressed,... + 'Position',[figstartx figstarty figwidth figheight],... + 'Color',DATA.GUISettings.BackgroundColor,... + 'NumberTitle','off'... + ); + +% load in image ad crop +offset = 20; +if ~exist('imagedata','var')|| isempty(imagedata) + if isdeployed + tmpimg = imread('drawing_guidance.png'); + else + tmpimg = imread(['+straintagging' filesep 'drawing_guidance.png']); + end + imwidth = floor(size(tmpimg,2)/4); + imheight = size(tmpimg,1)- 50; + img = imcrop(tmpimg,[2*imwidth 0 imwidth imheight]); +else + imwidth = size(imagedata,2); + imheight = size(imagedata,1); + img = imagedata; +end + +% add axes to the figure and show image +ax = axes(fig); +ax.Units = 'pixels'; +axeswidth = figwidth-2*offset; +axesheight = floor(axeswidth*imheight/imwidth); +ax.Position = [offset 135 axeswidth axesheight]; +imagesc(ax,img) +axis off; + +% add text message +if ~exist('txtmessage','var')|| isempty(txtmessage) + txtmessage = dprintf('Warning'); +end +txtposition = [offset 70 axeswidth 60]; +msgtextcontrol = uicontrol(fig,... + 'Style','text',... + 'Units','pixels',... + 'Position',txtposition,... + 'keypressfcn',@yeskeypressed,... + 'HorizontalAlignment', 'left',... + 'BackgroundColor',DATA.GUISettings.BackgroundColor,... + 'ForegroundColor',DATA.GUISettings.ForegroundColor,... + 'String',txtmessage); %#ok +% add buttons +buttonheight = 30; +yesbuttonposition = [offset offset axeswidth/2-10 buttonheight]; +yesbuttoncontrol = uicontrol(fig,... + 'Style','pushbutton',... + 'Units','pixels',... + 'Position',yesbuttonposition,... + 'Callback',@selection,... + 'BackgroundColor',DATA.GUISettings.BackgroundColor,... + 'ForegroundColor',DATA.GUISettings.ForegroundColor,... + 'String',dprintf('YES, continue'),... + 'UserData','yes'); %#ok + +nobuttonposition = [offset+axeswidth/2+10 offset axeswidth/2-10 buttonheight]; +nobuttoncontrol = uicontrol(fig,... + 'Style','pushbutton',... + 'Units','pixels',... + 'Position',nobuttonposition,... + 'Callback',@selection,... + 'BackgroundColor',DATA.GUISettings.BackgroundColor,... + 'ForegroundColor',DATA.GUISettings.ForegroundColor,... + 'String',dprintf('NO, return'),... + 'UserData','no'); %#ok + +uiwait(fig) + function selection(src,~) + str = src.UserData; + if contains(lower(str),'yes') + usersanswer = true; + else + usersanswer = false; + end + uiresume(fig) + close(fig) + end + + %---------------------------------- + function keypressed(fignum,evnt) %#ok + %---------------------------------- + key = getkey(evnt); + switch key + case {'y','Y'} + usersanswer = true; + uiresume(fig) + close(fig) + case {'n','N'} + usersanswer = true; + uiresume(fig) + close(fig) + otherwise + + end + + end +end