From 3bc4863771e1ebf3420bc7c0948751233ff0c44b Mon Sep 17 00:00:00 2001 From: gav-hsu Date: Thu, 16 May 2024 18:39:41 -0400 Subject: [PATCH 1/4] updated sliceshow --- .gitignore | 28 ++++++ brainCrop.m | 15 +++ meshByIso2mesh.m | 2 +- reviewRes.m | 15 +-- sliceshow.m | 243 ++++++++++++++++++++++++++++++++++++----------- start_seg.m | 4 +- visualizeRes.m | 15 +-- 7 files changed, 251 insertions(+), 71 deletions(-) create mode 100644 .gitignore create mode 100644 brainCrop.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca37d1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +example/c1MNI152_T1_1mm_ras_T1orT2.nii +example/c2MNI152_T1_1mm_ras_T1orT2.nii +example/c3MNI152_T1_1mm_ras_T1orT2.nii +example/c4MNI152_T1_1mm_ras_T1orT2.nii +example/c5MNI152_T1_1mm_ras_T1orT2.nii +example/c6MNI152_T1_1mm_ras_T1orT2.nii +example/MNI152_T1_1mm_20240516T173547_e.nii +example/MNI152_T1_1mm_20240516T173547_e.pos +example/MNI152_T1_1mm_20240516T173547_emag.nii +example/MNI152_T1_1mm_20240516T173547_mask_elec.nii +example/MNI152_T1_1mm_20240516T173547_mask_gel.nii +example/MNI152_T1_1mm_20240516T173547_ready.msh +example/MNI152_T1_1mm_20240516T173547_roastOptions.mat +example/MNI152_T1_1mm_20240516T173547_roastResult.mat +example/MNI152_T1_1mm_20240516T173547_usedElecArea.mat +example/MNI152_T1_1mm_20240516T173547_v.nii +example/MNI152_T1_1mm_20240516T173547_v.pos +example/MNI152_T1_1mm_20240516T173547.mat +example/MNI152_T1_1mm_20240516T173547.msh +example/MNI152_T1_1mm_20240516T173547.pro +example/MNI152_T1_1mm_ras_header.mat +example/MNI152_T1_1mm_ras_MNI.nii +example/MNI152_T1_1mm_ras_T1orT2_rmask.mat +example/MNI152_T1_1mm_ras_T1orT2_seg8.mat +example/MNI152_T1_1mm_ras_T1orT2_SPM_masks_MNI.nii +example/MNI152_T1_1mm_ras_T1orT2_SPM_masks.nii +example/MNI152_T1_1mm_ras.nii +example/MNI152_T1_1mm_roastLog diff --git a/brainCrop.m b/brainCrop.m new file mode 100644 index 0000000..4a856bd --- /dev/null +++ b/brainCrop.m @@ -0,0 +1,15 @@ +% Crops the image to the brain using segmentation +% Returns the upper and lower bounds of the brain in each direction +% column 1 = R/L, column 2 = A/P, column 3 = S/I +% (c) 2024 Gavin Hsu and Andrew Birnbaum + +function bbox = brainCrop(subj) + [dirname,baseFilename,ext] = fileparts(subj); + seg = [dirname,'\',baseFilename,'_masks',ext]; + data = load_untouch_nii(seg); + wm = data.img == 1; + thresh = [0,0,100]; + [bbox(1,1),bbox(2,1)]=bounds(find(sum(sum(wm,2),3)>thresh(1))); + [bbox(1,2),bbox(2,2)]=bounds(find(sum(sum(wm,1),3)>thresh(2))); + [bbox(1,3),bbox(2,3)]=bounds(find(sum(sum(wm,1),2)>thresh(3))); +end \ No newline at end of file diff --git a/meshByIso2mesh.m b/meshByIso2mesh.m index 614c50e..83feb0a 100644 --- a/meshByIso2mesh.m +++ b/meshByIso2mesh.m @@ -45,7 +45,7 @@ allMaskShow(data.img>0) = numOfTissue + 2; % sliceshow(allMask,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.') -sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni) +sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni,[]) drawnow % allMask = uint8(allMask); diff --git a/reviewRes.m b/reviewRes.m index d37d36e..b7077fc 100644 --- a/reviewRes.m +++ b/reviewRes.m @@ -70,6 +70,8 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) % (c) MultiPriors segmentation developed by Lukas Hirsch, and integrated into % ROAST by Andrew Birnbaum % April 2024 +% +% (c) May 2024 Gavin Hsu fprintf('\n\n'); disp('=============================================================') @@ -243,7 +245,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) if ~exist(subjRasRSPD,'file') error(['The subject MRI you provided ' subjRasRSPD ' does not exist. Check if you run through resampling or zero-padding if you tried to do that.']); else - data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni); drawnow + data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni,[]); drawnow end if ~isempty(optRoast.T2) %T2 specified @@ -251,7 +253,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) error(['T2 file ' optRoast.T2 ' does not exist. You used that to run ROAST but maybe later deleted it.']); else data = load_untouch_nii(optRoast.T2); - sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni); drawnow + sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni,[]); drawnow end end else @@ -298,7 +300,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) allMaskShow = masks.img; allMaskShow(gel.img>0) = numOfTissue + 1; allMaskShow(elec.img>0) = numOfTissue + 2; - sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni) + sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni,[]) drawnow else @@ -517,6 +519,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) nan_mask(find(mask)) = 1; cm = colormap(jet(2^11)); cm = [1 1 1;cm]; +bbox = brainCrop(subjRasRSPD); if isRoast @@ -528,13 +531,13 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) end figName = ['Voltage in Simulation: ' simTag]; - sliceshow(vol_all.*nan_mask,[],cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni); drawnow + sliceshow(vol_all.*nan_mask,[],cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni,bbox); drawnow figName = ['Electric field in Simulation: ' simTag]; for i=1:size(ef_all,4), ef_all(:,:,:,i) = ef_all(:,:,:,i).*nan_mask; end ef_mag = ef_mag.*nan_mask; dataShowVal = ef_mag(~isnan(ef_mag(:))); - sliceshow(ef_mag,[],cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni); drawnow + sliceshow(ef_mag,[],cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow else @@ -543,6 +546,6 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) dataShowVal = r.ef_mag(~isnan(r.ef_mag(:))); for i=1:size(r.targetCoord,1) figName = ['Electric field at Target ' num2str(i) ' in Targeting: ' tarTag]; - sliceshow(r.ef_mag,r.targetCoord(i,:),cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],r.ef_all,mri2mni); drawnow + sliceshow(r.ef_mag,r.targetCoord(i,:),cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],r.ef_all,mri2mni,bbox); drawnow end end \ No newline at end of file diff --git a/sliceshow.m b/sliceshow.m index f184bfd..5749c84 100644 --- a/sliceshow.m +++ b/sliceshow.m @@ -1,6 +1,4 @@ -function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) -% sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) -% +function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni,bbox) % sliceshow displays a 3D volume allowing the user to click on different % slices. If the variable "vecImg" is specified, sliceshow will also % overlay a 3D vectorial field represented by arrows on the slices. @@ -8,6 +6,9 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) % If pos is given as input, then the function will start the display with % the slices intersecting this position. Defaults to the middle of the % volume. +% +% Coordinates are editable. Enter the desired voxel or MNI coordinates to +% navigate to the desired position. % % color is the colormap the display will use. Defaults to 'jet'. % @@ -20,11 +21,29 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) % vecImg is the 3D vectorial field, e.g. an electric field. % % mri2mni is the mapping from MRI voxel space to the MNI space, so +% +% bbox is the output of brainCrop(). Use this to display only the brain. +% % sliceshow can display both the voxel and MNI coordinates. % % (c) Nov 02, 2017, Lucas C Parra % (c) June 29, 2018, Yu (Andy) Huang % (c) August 2019, Yu (Andy) Huang +% (c) 2024, Gavin Hsu and Andrew Birnbaum + +if nargin >= 2 && ~isempty(bbox) + minR = bbox(1,1); + maxR = bbox(2,1); + minA = bbox(1,2); + maxA = bbox(2,2); + minS = bbox(1,3); + maxS = bbox(2,3); + img = img(minR:maxR, minA:maxA, minS:maxS); +else + minR = 0; + minA = 0; + minS = 0; +end if nargin<1 || isempty(img) error('At least give us a volume to display') @@ -35,8 +54,10 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) if nargin<2 || isempty(pos) mydata.pos = round(size(img)/2); + mydata.pos_crop = mydata.pos + [minR,minA,minS]; else - mydata.pos=pos; + mydata.pos=pos-[minR,minA,minS]; + mydata.pos_crop = mydata.pos + [minR,minA,minS]; end if nargin<3 || isempty(color) @@ -70,6 +91,9 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) if nargin<7 || isempty(vecImg) mydata.vecImg = []; else + if nargin >= 2 && ~isempty(bbox) + vecImg = vecImg(minR:maxR, minA:maxA, minS:maxS,:); + end temp = size(vecImg); if any(temp(1:3)~=[Nx,Ny,Nz]) || temp(4)~=3 error('Vector field does not have correct size.'); @@ -86,22 +110,24 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni) error('Unrecognized format of the voxel-to-MNI mapping.'); end mydata.mri2mni = mri2mni; + mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); end -% link the calback function to new figure -fh = figure('WindowButtonDownFcn',@myCallback,'Name',figName,'NumberTitle','off'); - +whratio = 1.0187; %Width-to-height ratio +w = 8.5; %Width in inches +% link the callback function to new figure +fh = uifigure('WindowButtonDownFcn',@(src, event) myCallback(src, event, minR, minA, minS),'Name',figName,'NumberTitle','off','Units','inches','Position',[0,0,w,w/whratio],'AutoResizeChildren','off','SizeChangedFcn',@(src,event) figResize(src,event,minR,minA,minS)); +movegui(fh,'center') % store data as figure property set(fh,'UserData',mydata); +set(fh,'HandleVisibility','on') -% first display -showimages - - +% initial display +showimages(minR,minA,minS,fh) end -function myCallback(fh,~) -% This selects new position depending on which subplot a button is clicked. +function myCallback(fh,~,minR, minA, minS) +% Selects new position depending on which subplot is clicked on. % Updates display information in mydata. mydata = get(fh,'UserData'); @@ -112,78 +138,183 @@ function myCallback(fh,~) case mydata.h(2); mydata.pos([2 3]) = pos; case mydata.h(3); mydata.pos([1 2]) = pos; end +mydata.pos_crop = mydata.pos + [minR,minA,minS]; +mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); % if new position is valid, update mydata as figure property and display % otherwise do nothing if ~sum( mydata.pos<1 | mydata.pos>size(mydata.img) ) set(fh,'UserData',mydata); - showimages + showimages(minR,minA,minS,fh) end - end -function showimages -% Displays the image based on current mydata. +function showimages(minR,minA,minS,fh) +% Displays the image based on current UserData. % grab the stuff to display from figure -mydata = get(gcf,'UserData'); +mydata = get(fh,'UserData'); + +% Show the images and keep track of the axes that are generated +mytile = tiledlayout(fh,2,2,'Padding','tight','TileSpacing','none'); -% show the images and keep track of the axes that are generated -h(1)=subplot(2,2,1); -imagesc(squeeze(mydata.img(:,mydata.pos(2),:))'); d(1,:)=[1 3]; +h(1) = nexttile(mytile,1); +imagesc(h(1),squeeze(mydata.img(:,mydata.pos(2),:))'); d(1,:)=[1 3]; if ~isempty(mydata.vecImg) - hold on; + hold(h(1),'on'); rngx=1:5:size(mydata.xi,1); rngy=mydata.pos(2); rngz=1:5:size(mydata.xi,3); - quiver3(mydata.xi(rngx,rngy,rngz),mydata.zi(rngx,rngy,rngz),mydata.yi(rngx,rngy,rngz),... - mydata.vecImg(rngx,rngy,rngz,1),mydata.vecImg(rngx,rngy,rngz,3),mydata.vecImg(rngx,rngy,rngz,2),2,'color','k'); %,0.08,'nointerp'); - hold off; + quiver3(h(1),mydata.xi(rngx,rngy,rngz),mydata.zi(rngx,rngy,rngz),mydata.yi(rngx,rngy,rngz),... + mydata.vecImg(rngx,rngy,rngz,1),mydata.vecImg(rngx,rngy,rngz,3),mydata.vecImg(rngx,rngy,rngz,2),2,'color','k'); + hold(h(1),'off'); end -h(2)=subplot(2,2,2); -imagesc(squeeze(mydata.img(mydata.pos(1),:,:))'); d(2,:)=[2 3]; +axtoolbar(h(1),{}); + +h(2) = nexttile(mytile,2); +imagesc(h(2),squeeze(mydata.img(mydata.pos(1),:,:))'); d(2,:)=[2 3]; if ~isempty(mydata.vecImg) - hold on; + hold(h(2),'on'); rngx=mydata.pos(1); rngy=1:5:size(mydata.xi,2); rngz=1:5:size(mydata.xi,3); - quiver3(mydata.yi(rngx,rngy,rngz),mydata.zi(rngx,rngy,rngz),mydata.xi(rngx,rngy,rngz),... - mydata.vecImg(rngx,rngy,rngz,2),mydata.vecImg(rngx,rngy,rngz,3),mydata.vecImg(rngx,rngy,rngz,1),2,'color','k'); %,0.08,'nointerp'); - hold off; + quiver3(h(2),mydata.yi(rngx,rngy,rngz),mydata.zi(rngx,rngy,rngz),mydata.xi(rngx,rngy,rngz),... + mydata.vecImg(rngx,rngy,rngz,2),mydata.vecImg(rngx,rngy,rngz,3),mydata.vecImg(rngx,rngy,rngz,1),2,'color','k'); + hold(h(2),'off'); end -h(3)=subplot(2,2,3); -imagesc(squeeze(mydata.img(:,:,mydata.pos(3)))'); d(3,:)=[1 2]; +axtoolbar(h(2),{}); + +h(3) = nexttile(mytile,3); +imagesc(h(3),squeeze(mydata.img(:,:,mydata.pos(3)))'); d(3,:)=[1 2]; if ~isempty(mydata.vecImg) - hold on; + hold(h(3),'on'); rngx=1:5:size(mydata.xi,1); rngy=1:5:size(mydata.xi,2); rngz=mydata.pos(3); - quiver3(mydata.xi(rngx,rngy,rngz),mydata.yi(rngx,rngy,rngz),mydata.zi(rngx,rngy,rngz),... - mydata.vecImg(rngx,rngy,rngz,1),mydata.vecImg(rngx,rngy,rngz,2),mydata.vecImg(rngx,rngy,rngz,3),2,'color','k'); %,0.08,'nointerp'); - hold off; + quiver3(h(3),mydata.xi(rngx,rngy,rngz),mydata.yi(rngx,rngy,rngz),mydata.zi(rngx,rngy,rngz),... + mydata.vecImg(rngx,rngy,rngz,1),mydata.vecImg(rngx,rngy,rngz,2),mydata.vecImg(rngx,rngy,rngz,3),2,'color','k'); + hold(h(3),'off'); end +axtoolbar(h(3),{}); -% some aesthetics -val = mydata.img(mydata.pos(1),mydata.pos(2),mydata.pos(3)); +% Aesthetics +val = mydata.img(mydata.pos(1),mydata.pos(2),mydata.pos(3)); %EF value for i=1:3 - subplot(2,2,i); - hold on; plot(mydata.pos(d(i,1)),mydata.pos(d(i,2)),'o','color',ones(1,3)*0.4,'linewidth',3,'markersize',12); hold off; - axis xy; axis equal; axis tight; axis off; caxis(mydata.clim); - title([num2str(mydata.pos(d(i,:))) ': ' num2str(val,'%.2f')]) + han = nexttile(mytile,i); + % Place position marker + hold(han,'on'); plot(han,mydata.pos(d(i,1)),mydata.pos(d(i,2)),'o','color','m','linewidth',3,'markersize',12); hold(han,'off'); + axis(han,'xy'); axis(han,'equal'); axis(han,'tight'); axis(han,'off'); clim(han,mydata.clim); + stackorder = get(h(i),'Children'); + if size(stackorder,1)>2 + set(h(i),'Children',[stackorder(1),stackorder(2),stackorder(3)]); + end + % Show crosshairs + xline(han,mydata.pos(d(i,1))); yline(han,mydata.pos(d(i,2))); end +% Set x- and y-lims equal in all views (for uniform scaling) +xlim(h,[0,max(size(mydata.img))]) +ylim(h,[0,max(size(mydata.img))]) + +h(4) = nexttile(mytile,4); axis(h(4),'off'); box(h(4),'off'); clim(h(4),mydata.clim); axtoolbar(h(4),{}); +mydata.pos_crop = mydata.pos + [minR,minA,minS]; + +% Arrange user input and coordinates in a UI Panel +ip = uipanel(fh,'BackgroundColor','white','AutoResizeChildren','off'); +ip.Units = 'normalized'; +ip.Position = [0.5,0,0.5,0.3]; +ip.BorderType = 'none'; +ip.Units = 'pixels'; +panelsize = ip.Position; +ip.Units = 'normalized'; +l = 0.28*panelsize(3); %left reference point +b = 0.59*panelsize(4); %bottom reference point +FSEF = 24; %Font size for displaying EF +FSc = 20; %Font size for coordinates +padding = 10; +%Display value: +uilabel(ip,'Position',[l-3.4*FSc,b-3*FSc,FSEF*12,FSEF+padding],'Text',strcat(mydata.label),'FontSize',FSEF,'FontWeight','bold','HorizontalAlignment','center'); +uilabel(ip,'Position',[l-3.4*FSc,b-4.5*FSc,FSEF*12,FSEF+padding],'Text',num2str(val,'%.2f'),'FontSize',FSEF,'FontWeight','bold','HorizontalAlignment','center'); +%Display voxel coordinates (callback below): +uilabel(ip,'Position',[l-3.4*FSc,b+2*FSc,3.1*FSc,FSc+padding],'Text','Voxel','FontSize',FSc,'FontWeight','bold'); +efx = uieditfield(ip,'Position',[l+FSc,b+2*FSc,2.5*FSc,FSc+padding],'Tag','x','FontSize',FSc,'ValueChangedFcn',@(src,event) updateX(src,event,minR,minA,minS,fh),'HorizontalAlignment','right','FontWeight','bold'); +efx.Value = num2str(mydata.pos_crop(1)); +uilabel(ip,'Position',[l,b+2*FSc,1.25*FSc,FSc+padding],'Text','X','FontSize',FSc); +efy = uieditfield(ip,'Position',[l+5.25*FSc,b+2*FSc,2.5*FSc,FSc+padding],'Tag','y','FontSize',FSc,'ValueChangedFcn',@(src,event) updateX(src,event,minR,minA,minS,fh),'HorizontalAlignment','right','FontWeight','bold'); +efy.Value = num2str(mydata.pos_crop(2)); +uilabel(ip,'Position',[l+4.25*FSc,b+2*FSc,1.25*FSc,FSc+padding],'Text','Y','FontSize',FSc); +efz = uieditfield(ip,'Position',[l+9.5*FSc,b+2*FSc,2.5*FSc,FSc+padding],'Tag','z','FontSize',FSc,'ValueChangedFcn',@(src,event) updateX(src,event,minR,minA,minS,fh),'HorizontalAlignment','right','FontWeight','bold'); +efz.Value = num2str(mydata.pos_crop(3)); +uilabel(ip,'Position',[l+8.5*FSc,b+2*FSc,1.25*FSc,FSc+padding],'Text','Z','FontSize',FSc); + +%Display MNI coordinates (callback below): if ~isempty(mydata.mri2mni) - h(4) = subplot(2,2,4); axis off; caxis(mydata.clim); - mniCoord = round(mydata.mri2mni*[mydata.pos 1]'); - coordInfo = {['Voxel: ' num2str(mydata.pos(1)) ',' num2str(mydata.pos(2)) ',' num2str(mydata.pos(3))],... - ['MNI: ' num2str(mniCoord(1)) ',' num2str(mniCoord(2)) ',' num2str(mniCoord(3))]}; - title(h(4), coordInfo,'FontSize',16); + uilabel(ip,'Position',[l-3.4*FSc,b,3.1*FSc,FSc+padding],'Text','MNI','FontSize',FSc,'FontWeight','bold'); + efxm = uieditfield(ip,'Position',[l+FSc,b,2.5*FSc,FSc+padding],'Tag','x','FontSize',FSc,'ValueChangedFcn',@(src,event) updateXMNI(src,event,minR,minA,minS,fh),'HorizontalAlignment','right','FontWeight','bold'); + efxm.Value = num2str(mydata.mnipos(1)); + uilabel(ip,'Position',[l,b,1.25*FSc,FSc+padding],'Text','X','FontSize',FSc); + efym = uieditfield(ip,'Position',[l+5.25*FSc,b,2.5*FSc,FSc+padding],'Tag','y','FontSize',FSc,'ValueChangedFcn',@(src,event) updateXMNI(src,event,minR,minA,minS,fh),'HorizontalAlignment','right','FontWeight','bold'); + efym.Value = num2str(mydata.mnipos(2)); + uilabel(ip,'Position',[l+4.25*FSc,b,1.25*FSc,FSc+padding],'Text','Y','FontSize',FSc); + efzm = uieditfield(ip,'Position',[l+9.5*FSc,b,2.5*FSc,FSc+padding],'Tag','z','FontSize',FSc,'ValueChangedFcn',@(src,event) updateXMNI(src,event,minR,minA,minS,fh),'HorizontalAlignment','right','FontWeight','bold'); + efzm.Value = num2str(mydata.mnipos(3)); + uilabel(ip,'Position',[l+8.5*FSc,b,1.25*FSc,FSc+padding],'Text','Z','FontSize',FSc); end -if ~isempty(mydata.label) - h(4) = subplot(2,2,4); axis off; caxis(mydata.clim); - h(5) = colorbar('west'); - set(h(5),'YAxisLocation','right','FontSize',18); - title(h(5), mydata.label,'FontSize',18); -end +% Display colorbar +h(5) = colorbar(nexttile(mytile,2),'southoutside'); +set(h(5),'YAxisLocation','bottom','FontSize',16); +h(5).Label.String = mydata.label; -colormap(mydata.color); +colormap(fh,mydata.color); +set(fh,'color','w') mydata.h=h; -set(gcf,'UserData',mydata); +set(fh,'UserData',mydata); +end + +function updateX(src,event,minR, minA, minS,fh) +% Update figure to display location specified by voxel coordinate input +mydata = get(fh,'UserData'); +if ~isempty(str2double(event.Value)) + switch src.Tag + case 'x' + mydata.pos(1) = round(str2double(event.Value))-minR; + mydata.pos_crop(1) = str2double(event.Value); + case 'y' + mydata.pos(2) = round(str2double(event.Value))-minA; + mydata.pos_crop(2) = str2double(event.Value); + case 'z' + mydata.pos(3) = round(str2double(event.Value))-minS; + mydata.pos_crop(3) = str2double(event.Value); + end + mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); +end +if ~sum( mydata.pos<1 | mydata.pos>size(mydata.img) ) + set(fh,'UserData',mydata); + showimages(minR,minA,minS,fh) +end +end +function updateXMNI(src,event,minR, minA, minS,fh) +% Update figure to display location specified by MNI coordinate input +mydata = get(fh,'UserData'); +if ~isempty(str2double(event.Value)) + switch src.Tag + case 'x' + mydata.mnipos(1) = round(str2double(event.Value)); + case 'y' + mydata.mnipos(2) = round(str2double(event.Value)); + case 'z' + mydata.mnipos(3) = round(str2double(event.Value)); + end + mydata.pos_crop = round(mydata.mri2mni\mydata.mnipos); + mydata.pos(1) = mydata.pos_crop(1)-minR; + mydata.pos(2) = mydata.pos_crop(2)-minA; + mydata.pos(3) = mydata.pos_crop(3)-minS; +end +if ~sum( mydata.pos<1 | mydata.pos>size(mydata.img) ) + set(fh,'UserData',mydata); + showimages(minR,minA,minS,fh) +end +end + +function figResize(fh,~,minR,minA,minS) + if ~isempty(fh.Children) + showimages(minR,minA,minS,fh) + end end \ No newline at end of file diff --git a/start_seg.m b/start_seg.m index cec66ab..1857fb2 100644 --- a/start_seg.m +++ b/start_seg.m @@ -62,7 +62,7 @@ function start_seg(T1,T2,Template,norm) if strcmp(ext,'.hdr'), ref = [dirname filesep t1name '.img']; end t1Data = load_untouch_nii(ref); - sliceshow(t1Data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.'); drawnow + sliceshow(t1Data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],[],[]); drawnow matlabbatch{1}.spm.spatial.preproc.channel.vols = {ref}; % image to be segmented matlabbatch{1}.spm.spatial.preproc.channel.biasreg = 0.001; % P(beta) % 0.0001; @@ -81,7 +81,7 @@ function start_seg(T1,T2,Template,norm) % fprintf('Using %s to segment T1 and T2 images: %s %s\n', Template, ref, ref2); t2Data = load_untouch_nii(ref2); - sliceshow(t2Data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.'); drawnow + sliceshow(t2Data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],[],[]); drawnow matlabbatch{1}.spm.spatial.preproc.channel(2).vols = {ref2}; % the 2nd image aiding segmentation matlabbatch{1}.spm.spatial.preproc.channel(2).biasreg = 0.001; % 0.0001; diff --git a/visualizeRes.m b/visualizeRes.m index 9859ba2..5b4ec12 100644 --- a/visualizeRes.m +++ b/visualizeRes.m @@ -8,6 +8,8 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent % yhuang16@citymail.cuny.edu % April 2018 % August 2019 callable by roast_target() +% +% (c) May 2024 Gavin Hsu and Andrew Birnbaum if ndims(varargin{1})==3 isRoast = 1; @@ -33,11 +35,11 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent if showAll if ~strcmp(subjName,'nyhead') disp('showing MRI and segmentations...'); - data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni); drawnow + data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni,[]); drawnow if ~isempty(T2) %T2 specified data = load_untouch_nii(T2); - sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni); drawnow + sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni,[]); drawnow end else disp('NEW YORK HEAD selected, there is NO MRI for it to show.') @@ -62,7 +64,7 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent allMaskShow = masks.img; allMaskShow(gel.img>0) = numOfTissue + 1; allMaskShow(elec.img>0) = numOfTissue + 2; - sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni) + sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni,[]) drawnow end @@ -232,10 +234,11 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent nan_mask_brain(find(brain)) = 1; cm = colormap(jet(2^11)); cm = [1 1 1;cm]; +bbox = brainCrop(segOut); if isRoast figName = ['Voltage in Simulation: ' uniTag]; - sliceshow(vol_all.*nan_mask_brain,[],cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni); drawnow + sliceshow(vol_all.*nan_mask_brain,[],cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni,bbox); drawnow end for i=1:size(ef_all,4), ef_all(:,:,:,i) = ef_all(:,:,:,i).*nan_mask_brain; end @@ -243,11 +246,11 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent dataShowVal = ef_mag(~isnan(ef_mag(:))); if isRoast figName = ['Electric field in Simulation: ' uniTag]; - sliceshow(ef_mag,[],cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni); drawnow + sliceshow(ef_mag,[],cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow else for i=1:size(targetCoord,1) figName = ['Electric field at Target ' num2str(i) ' in Targeting: ' uniTag]; - sliceshow(ef_mag,targetCoord(i,:),cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni); drawnow + sliceshow(ef_mag,targetCoord(i,:),cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow end end \ No newline at end of file From 4fe252f429eaf9f9d0b2ed7f154545e1471a0201 Mon Sep 17 00:00:00 2001 From: Yu Andy Huang Date: Tue, 21 May 2024 15:56:06 -0400 Subject: [PATCH 2/4] fix some issues of the new sliceshow --- brainCrop.m | 4 +-- meshByIso2mesh.m | 2 +- releasingNotes.txt | 2 ++ reviewRes.m | 20 ++++++++---- sliceshow.m | 79 +++++++++++++++++++++++----------------------- start_seg.m | 4 +-- visualizeRes.m | 12 +++---- 7 files changed, 65 insertions(+), 58 deletions(-) diff --git a/brainCrop.m b/brainCrop.m index 4a856bd..24811c5 100644 --- a/brainCrop.m +++ b/brainCrop.m @@ -4,8 +4,8 @@ % (c) 2024 Gavin Hsu and Andrew Birnbaum function bbox = brainCrop(subj) - [dirname,baseFilename,ext] = fileparts(subj); - seg = [dirname,'\',baseFilename,'_masks',ext]; + [dirname,baseFilename] = fileparts(subj); + seg = [dirname filesep baseFilename,'_masks.nii']; data = load_untouch_nii(seg); wm = data.img == 1; thresh = [0,0,100]; diff --git a/meshByIso2mesh.m b/meshByIso2mesh.m index 83feb0a..614c50e 100644 --- a/meshByIso2mesh.m +++ b/meshByIso2mesh.m @@ -45,7 +45,7 @@ allMaskShow(data.img>0) = numOfTissue + 2; % sliceshow(allMask,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.') -sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni,[]) +sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni) drawnow % allMask = uint8(allMask); diff --git a/releasingNotes.txt b/releasingNotes.txt index 7b4cbe9..3a725b9 100644 --- a/releasingNotes.txt +++ b/releasingNotes.txt @@ -16,6 +16,8 @@ Added a function to set the headers of the MRI and segmentation masks so that th Added code to handle MRIs with nonzero qform in their header. +Upgraded the sliceshow() function for better visualization of slices in a 3D volume. + ROAST V3.0 (codename: Hell's Kitchen) -- 2019/09/02: diff --git a/reviewRes.m b/reviewRes.m index b7077fc..c6b67c0 100644 --- a/reviewRes.m +++ b/reviewRes.m @@ -71,7 +71,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) % ROAST by Andrew Birnbaum % April 2024 % -% (c) May 2024 Gavin Hsu +% (c) May 2024, sliceshow improved by Gavin Hsu and Andrew Birnbaum fprintf('\n\n'); disp('=============================================================') @@ -245,7 +245,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) if ~exist(subjRasRSPD,'file') error(['The subject MRI you provided ' subjRasRSPD ' does not exist. Check if you run through resampling or zero-padding if you tried to do that.']); else - data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni,[]); drawnow + data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni); drawnow end if ~isempty(optRoast.T2) %T2 specified @@ -253,7 +253,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) error(['T2 file ' optRoast.T2 ' does not exist. You used that to run ROAST but maybe later deleted it.']); else data = load_untouch_nii(optRoast.T2); - sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni,[]); drawnow + sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni); drawnow end end else @@ -300,7 +300,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) allMaskShow = masks.img; allMaskShow(gel.img>0) = numOfTissue + 1; allMaskShow(elec.img>0) = numOfTissue + 2; - sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni,[]) + sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni) drawnow else @@ -519,7 +519,13 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) nan_mask(find(mask)) = 1; cm = colormap(jet(2^11)); cm = [1 1 1;cm]; -bbox = brainCrop(subjRasRSPD); +if strcmp(tissue,'white') | strcmp(tissue,'gray') | strcmp(tissue,'brain') + bbox = brainCrop(subjRasRSPDSeg); + pos = round(mean(bbox)); +else + bbox = []; + pos = []; +end if isRoast @@ -531,13 +537,13 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) end figName = ['Voltage in Simulation: ' simTag]; - sliceshow(vol_all.*nan_mask,[],cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni,bbox); drawnow + sliceshow(vol_all.*nan_mask,pos,cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni,bbox); drawnow figName = ['Electric field in Simulation: ' simTag]; for i=1:size(ef_all,4), ef_all(:,:,:,i) = ef_all(:,:,:,i).*nan_mask; end ef_mag = ef_mag.*nan_mask; dataShowVal = ef_mag(~isnan(ef_mag(:))); - sliceshow(ef_mag,[],cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow + sliceshow(ef_mag,pos,cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow else diff --git a/sliceshow.m b/sliceshow.m index 5749c84..e9259ca 100644 --- a/sliceshow.m +++ b/sliceshow.m @@ -20,7 +20,7 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni,bbox) % % vecImg is the 3D vectorial field, e.g. an electric field. % -% mri2mni is the mapping from MRI voxel space to the MNI space, so +% mri2mni is the mapping from MRI voxel space to the MNI space. % % bbox is the output of brainCrop(). Use this to display only the brain. % @@ -31,33 +31,14 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni,bbox) % (c) August 2019, Yu (Andy) Huang % (c) 2024, Gavin Hsu and Andrew Birnbaum -if nargin >= 2 && ~isempty(bbox) - minR = bbox(1,1); - maxR = bbox(2,1); - minA = bbox(1,2); - maxA = bbox(2,2); - minS = bbox(1,3); - maxS = bbox(2,3); - img = img(minR:maxR, minA:maxA, minS:maxS); -else - minR = 0; - minA = 0; - minS = 0; -end - if nargin<1 || isempty(img) - error('At least give us a volume to display') + error('At least give us a volume to display'); else [Nx,Ny,Nz] = size(img); - mydata.img = img; end if nargin<2 || isempty(pos) - mydata.pos = round(size(img)/2); - mydata.pos_crop = mydata.pos + [minR,minA,minS]; -else - mydata.pos=pos-[minR,minA,minS]; - mydata.pos_crop = mydata.pos + [minR,minA,minS]; + pos = round(size(img)/2); end if nargin<3 || isempty(color) @@ -89,18 +70,12 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni,bbox) end if nargin<7 || isempty(vecImg) - mydata.vecImg = []; + vecImg = []; else - if nargin >= 2 && ~isempty(bbox) - vecImg = vecImg(minR:maxR, minA:maxA, minS:maxS,:); - end temp = size(vecImg); if any(temp(1:3)~=[Nx,Ny,Nz]) || temp(4)~=3 error('Vector field does not have correct size.'); end - mydata.vecImg = vecImg; - [xi,yi,zi] = ndgrid(1:Nx,1:Ny,1:Nz); - mydata.xi = xi; mydata.yi = yi; mydata.zi = zi; end if nargin<8 || isempty(mri2mni) @@ -110,9 +85,33 @@ function sliceshow(img,pos,color,clim,label,figName,vecImg,mri2mni,bbox) error('Unrecognized format of the voxel-to-MNI mapping.'); end mydata.mri2mni = mri2mni; - mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); end +if nargin<9 || isempty(bbox) + minR = 1; minA = 1; minS = 1; + maxR = Nx; maxA = Ny; maxS = Nz; +else + minR = bbox(1,1); + maxR = bbox(2,1); + minA = bbox(1,2); + maxA = bbox(2,2); + minS = bbox(1,3); + maxS = bbox(2,3); +end + +% adjustment for bbox +img = img(minR:maxR, minA:maxA, minS:maxS); mydata.img = img; +temp = pos-[minR-1,minA-1,minS-1]; +if any(temp<=0), error('Voxel selected falls outside of the bounding box.'); end +mydata.pos = temp; +mydata.pos_crop = mydata.pos + [minR-1,minA-1,minS-1]; +if ~isempty(vecImg), vecImg = vecImg(minR:maxR, minA:maxA, minS:maxS,:); end +mydata.vecImg = vecImg; +[Nx,Ny,Nz] = size(img); +[xi,yi,zi] = ndgrid(1:Nx,1:Ny,1:Nz); +mydata.xi = xi; mydata.yi = yi; mydata.zi = zi; +if ~isempty(mydata.mri2mni), mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); end + whratio = 1.0187; %Width-to-height ratio w = 8.5; %Width in inches % link the callback function to new figure @@ -138,8 +137,8 @@ function myCallback(fh,~,minR, minA, minS) case mydata.h(2); mydata.pos([2 3]) = pos; case mydata.h(3); mydata.pos([1 2]) = pos; end -mydata.pos_crop = mydata.pos + [minR,minA,minS]; -mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); +mydata.pos_crop = mydata.pos + [minR-1,minA-1,minS-1]; +if ~isempty(mydata.mri2mni), mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); end % if new position is valid, update mydata as figure property and display % otherwise do nothing @@ -211,7 +210,7 @@ function showimages(minR,minA,minS,fh) ylim(h,[0,max(size(mydata.img))]) h(4) = nexttile(mytile,4); axis(h(4),'off'); box(h(4),'off'); clim(h(4),mydata.clim); axtoolbar(h(4),{}); -mydata.pos_crop = mydata.pos + [minR,minA,minS]; +mydata.pos_crop = mydata.pos + [minR-1,minA-1,minS-1]; % Arrange user input and coordinates in a UI Panel ip = uipanel(fh,'BackgroundColor','white','AutoResizeChildren','off'); @@ -273,16 +272,16 @@ function updateX(src,event,minR, minA, minS,fh) if ~isempty(str2double(event.Value)) switch src.Tag case 'x' - mydata.pos(1) = round(str2double(event.Value))-minR; + mydata.pos(1) = round(str2double(event.Value))-(minR-1); mydata.pos_crop(1) = str2double(event.Value); case 'y' - mydata.pos(2) = round(str2double(event.Value))-minA; + mydata.pos(2) = round(str2double(event.Value))-(minA-1); mydata.pos_crop(2) = str2double(event.Value); case 'z' - mydata.pos(3) = round(str2double(event.Value))-minS; + mydata.pos(3) = round(str2double(event.Value))-(minS-1); mydata.pos_crop(3) = str2double(event.Value); end - mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); + if ~isempty(mydata.mri2mni), mydata.mnipos = round(mydata.mri2mni*[mydata.pos_crop 1]'); end end if ~sum( mydata.pos<1 | mydata.pos>size(mydata.img) ) set(fh,'UserData',mydata); @@ -303,9 +302,9 @@ function updateXMNI(src,event,minR, minA, minS,fh) mydata.mnipos(3) = round(str2double(event.Value)); end mydata.pos_crop = round(mydata.mri2mni\mydata.mnipos); - mydata.pos(1) = mydata.pos_crop(1)-minR; - mydata.pos(2) = mydata.pos_crop(2)-minA; - mydata.pos(3) = mydata.pos_crop(3)-minS; + mydata.pos(1) = mydata.pos_crop(1)-(minR-1); + mydata.pos(2) = mydata.pos_crop(2)-(minA-1); + mydata.pos(3) = mydata.pos_crop(3)-(minS-1); end if ~sum( mydata.pos<1 | mydata.pos>size(mydata.img) ) set(fh,'UserData',mydata); diff --git a/start_seg.m b/start_seg.m index 1857fb2..cec66ab 100644 --- a/start_seg.m +++ b/start_seg.m @@ -62,7 +62,7 @@ function start_seg(T1,T2,Template,norm) if strcmp(ext,'.hdr'), ref = [dirname filesep t1name '.img']; end t1Data = load_untouch_nii(ref); - sliceshow(t1Data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],[],[]); drawnow + sliceshow(t1Data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.'); drawnow matlabbatch{1}.spm.spatial.preproc.channel.vols = {ref}; % image to be segmented matlabbatch{1}.spm.spatial.preproc.channel.biasreg = 0.001; % P(beta) % 0.0001; @@ -81,7 +81,7 @@ function start_seg(T1,T2,Template,norm) % fprintf('Using %s to segment T1 and T2 images: %s %s\n', Template, ref, ref2); t2Data = load_untouch_nii(ref2); - sliceshow(t2Data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],[],[]); drawnow + sliceshow(t2Data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.'); drawnow matlabbatch{1}.spm.spatial.preproc.channel(2).vols = {ref2}; % the 2nd image aiding segmentation matlabbatch{1}.spm.spatial.preproc.channel(2).biasreg = 0.001; % 0.0001; diff --git a/visualizeRes.m b/visualizeRes.m index 5b4ec12..f568996 100644 --- a/visualizeRes.m +++ b/visualizeRes.m @@ -9,7 +9,7 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent % April 2018 % August 2019 callable by roast_target() % -% (c) May 2024 Gavin Hsu and Andrew Birnbaum +% (c) May 2024, sliceshow improved by Gavin Hsu and Andrew Birnbaum if ndims(varargin{1})==3 isRoast = 1; @@ -35,11 +35,11 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent if showAll if ~strcmp(subjName,'nyhead') disp('showing MRI and segmentations...'); - data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni,[]); drawnow + data = load_untouch_nii(subjRasRSPD); sliceshow(data.img,[],'gray',[],[],'MRI: Click anywhere to navigate.',[],mri2mni); drawnow if ~isempty(T2) %T2 specified data = load_untouch_nii(T2); - sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni,[]); drawnow + sliceshow(data.img,[],'gray',[],[],'MRI: T2. Click anywhere to navigate.',[],mri2mni); drawnow end else disp('NEW YORK HEAD selected, there is NO MRI for it to show.') @@ -64,7 +64,7 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent allMaskShow = masks.img; allMaskShow(gel.img>0) = numOfTissue + 1; allMaskShow(elec.img>0) = numOfTissue + 2; - sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni,[]) + sliceshow(allMaskShow,[],[],[],'Tissue index','Segmentation. Click anywhere to navigate.',[],mri2mni) drawnow end @@ -238,7 +238,7 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent if isRoast figName = ['Voltage in Simulation: ' uniTag]; - sliceshow(vol_all.*nan_mask_brain,[],cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni,bbox); drawnow + sliceshow(vol_all.*nan_mask_brain,round(mean(bbox)),cm,[],'Voltage (mV)',[figName '. Click anywhere to navigate.'],[],mri2mni,bbox); drawnow end for i=1:size(ef_all,4), ef_all(:,:,:,i) = ef_all(:,:,:,i).*nan_mask_brain; end @@ -246,7 +246,7 @@ function visualizeRes(subj,subjRasRSPD,spmOut,segOut,T2,node,elem,face,inCurrent dataShowVal = ef_mag(~isnan(ef_mag(:))); if isRoast figName = ['Electric field in Simulation: ' uniTag]; - sliceshow(ef_mag,[],cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow + sliceshow(ef_mag,round(mean(bbox)),cm,[min(dataShowVal) prctile(dataShowVal,95)],'Electric field (V/m)',[figName '. Click anywhere to navigate.'],ef_all,mri2mni,bbox); drawnow else for i=1:size(targetCoord,1) From 165c21aa23a4697e4af2522e822df47198a5c6ac Mon Sep 17 00:00:00 2001 From: Yu Andy Huang Date: Tue, 21 May 2024 17:29:09 -0400 Subject: [PATCH 3/4] a minor issue --- reviewRes.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reviewRes.m b/reviewRes.m index c6b67c0..70cf492 100644 --- a/reviewRes.m +++ b/reviewRes.m @@ -519,7 +519,7 @@ function reviewRes(subj,simTag,tissue,fastRender,tarTag) nan_mask(find(mask)) = 1; cm = colormap(jet(2^11)); cm = [1 1 1;cm]; -if strcmp(tissue,'white') | strcmp(tissue,'gray') | strcmp(tissue,'brain') +if strcmp(tissue,'white') || strcmp(tissue,'gray') || strcmp(tissue,'brain') bbox = brainCrop(subjRasRSPDSeg); pos = round(mean(bbox)); else From 47efc9ca215360731d767237975a4790237b4b9c Mon Sep 17 00:00:00 2001 From: Yu Andy Huang Date: Tue, 21 May 2024 17:35:17 -0400 Subject: [PATCH 4/4] Delete .gitignore --- .gitignore | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ca37d1e..0000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -example/c1MNI152_T1_1mm_ras_T1orT2.nii -example/c2MNI152_T1_1mm_ras_T1orT2.nii -example/c3MNI152_T1_1mm_ras_T1orT2.nii -example/c4MNI152_T1_1mm_ras_T1orT2.nii -example/c5MNI152_T1_1mm_ras_T1orT2.nii -example/c6MNI152_T1_1mm_ras_T1orT2.nii -example/MNI152_T1_1mm_20240516T173547_e.nii -example/MNI152_T1_1mm_20240516T173547_e.pos -example/MNI152_T1_1mm_20240516T173547_emag.nii -example/MNI152_T1_1mm_20240516T173547_mask_elec.nii -example/MNI152_T1_1mm_20240516T173547_mask_gel.nii -example/MNI152_T1_1mm_20240516T173547_ready.msh -example/MNI152_T1_1mm_20240516T173547_roastOptions.mat -example/MNI152_T1_1mm_20240516T173547_roastResult.mat -example/MNI152_T1_1mm_20240516T173547_usedElecArea.mat -example/MNI152_T1_1mm_20240516T173547_v.nii -example/MNI152_T1_1mm_20240516T173547_v.pos -example/MNI152_T1_1mm_20240516T173547.mat -example/MNI152_T1_1mm_20240516T173547.msh -example/MNI152_T1_1mm_20240516T173547.pro -example/MNI152_T1_1mm_ras_header.mat -example/MNI152_T1_1mm_ras_MNI.nii -example/MNI152_T1_1mm_ras_T1orT2_rmask.mat -example/MNI152_T1_1mm_ras_T1orT2_seg8.mat -example/MNI152_T1_1mm_ras_T1orT2_SPM_masks_MNI.nii -example/MNI152_T1_1mm_ras_T1orT2_SPM_masks.nii -example/MNI152_T1_1mm_ras.nii -example/MNI152_T1_1mm_roastLog