From 2399e5095fa905dc002cde5e879198efcc5febad Mon Sep 17 00:00:00 2001 From: p147685 Date: Thu, 16 Apr 2020 16:40:31 +0200 Subject: [PATCH] The alpha version. The first working version. --- GIFT_Clean/GiftIcaReport.m | 322 ++++++++++++++++++++++++++-- GIFT_Clean/UnityTestGiftIcaReport.m | 26 ++- 2 files changed, 325 insertions(+), 23 deletions(-) diff --git a/GIFT_Clean/GiftIcaReport.m b/GIFT_Clean/GiftIcaReport.m index 94a2a4c..d91a78b 100644 --- a/GIFT_Clean/GiftIcaReport.m +++ b/GIFT_Clean/GiftIcaReport.m @@ -1,21 +1,49 @@ classdef GiftIcaReport + case obj.OrientationOptions obj.Orientation=val; otherwise id = 'GiftIcaReport:set_orientation:invalid_orientation'; msg = sprintf('%s\n%s\n%s\t%s\t%s\n',... 'invalid option for orientation',... 'pick one of the following options',... - obj.OrientationOptions{:}); %#ok + obj.OrientationOptions{:}); throw(MException(id,msg)); end end - function set.SliceNumbers(obj,val) - if isnumeric(val) && ~any(val<1) - obj.SliceNumbers=val; + function set.PlotSliceNumbers(obj,val) + if isempty(val) + if ~isempty(obj.ImageData) && ~isempty(obj.NPlots) + %autofill the plotslicenumbers + switch lower(obj.Orientation) + case 'tra' + nmax=size(obj.ImageData,3) + case 'cor' + nmax=size(obj.ImageData,2) + case 'sag' + nmax=size(obj.ImageData,1); + otherwise + return; + end + obj.SliceNumbersInternal=round(linspace(1,nmax,obj.NPlots)); + end else - id = 'GiftIcaReport:set_slicenumbers:invalid_input'; + if isnumeric(val) && ~any(val<1) + obj.SliceNumbersInternal=val; + obj.NSlicesInternal=numel(val); + else + id = 'GiftIcaReport:set_slicenumbers:invalid_input'; + msg = sprintf('invalid input for slicenumbers'); + throw(MException(id,msg)); + end + end + end + + function val=get.PlotSliceNumbers(obj) + val=obj.SliceNumbersInternal; + end + + function set.NPlots(obj,val) + if isnumeric(val) && numel(val)==1 && val>0 + tmp=obj.SliceNumbersInternal; + if ~isempty(tmp) && val<=numel(tmp) + obj.PlotSliceNumbers=tmp(1:val); + else + obj.NSlicesInternal=val; + obj.PlotSliceNumbers=[]; + end + else + id = 'GiftIcaReport:set_NSlices:invalid_input'; msg = sprintf('invalid input for slicenumbers'); throw(MException(id,msg)); end + end + + function val=get.NPlots(obj) + val=obj.NSlicesInternal; + end + + function set.ImageLimits(obj,val) + if isnumeric(val) && numel(val)==2 + obj.CLim=transpose(sort(val(:))); %guarante it is a row vector + else + id = 'GiftIcaReport:setImageLimits:invalid_input'; + msg = sprintf('Invalid input, set limits to [min max]'); + throw(MException(id,msg)); + end + end + + function val=get.ImageLimits(obj) + val=obj.CLim; + end + + function set.Layout(obj,val) + switch lower(val) + case {'north','south','east','west',''} + obj.Layout=val; + otherwise + id = 'GiftIcaReport:setLayout:invalid_input'; + msg = sprintf('Invalid input for Layout.\n Use north east south, west or empty value'); + throw(MException(id,msg)); + end + end + end + methods %user callable functions + function LoadData(obj) + % read ICA file + [d,f,~]=fileparts(obj.ICAfile{1}); + obj.PData=spm_select('ExtFPList',d,f,1:10000); + obj.VData=spm_vol(obj.PData); + obj.ImageData=spm_read_vols(obj.VData); + % read TimeCourse file + [d,f,~]=fileparts(obj.TCfile{1}); + obj.PTimeCourse=spm_select('ExtFPList',d,f,1:10000); + obj.VTimeCourse=spm_vol(obj.PTimeCourse); + obj.TimeCourseData=spm_read_vols(obj.VTimeCourse); + if isempty(obj.PlotSliceNumbers) %auto set the slice numbers + obj.PlotSliceNumbers([]); + end + end + + function BuildFigure(obj) + if isempty(obj.FigureObject) + obj.FigureObject=figure; + end + figure(obj.FigureObject); + clf; + [nrow,ncol] = obj.getrowcol; + obj.TCPlot={}; + obj.SLPlot=cell(nrow,ncol); + switch lower(obj.Layout) + case {'north','n'} + r=nrow+1; + c=ncol; + PlRow=setdiff(1:r,1); + PlCol=1:c; + obj.TCPlot={subplot(r,1,1)}; + case {'east','e'} + r=nrow; + c=ncol+1; + PlRow=1:r; + PlCol=setdiff(1:c,1); + obj.TCPlot={subplot(1,c,c)}; + case {'south','s'} + r=nrow+1; + c=ncol; + PlRow=setdiff(1:r,r); + PlCol=1:c; + obj.TCPlot={subplot(r,1,r)}; + case {'west','w'} + r=nrow; + c=ncol+1; + PlRow=1:r; + PlCol=setdiff(1:c,1); + obj.TCPlot={subplot(1,c,1)}; + otherwise %center option + r=nrow+1; + c=ncol; + PlRow=setdiff(1:r,floor(r/2)); + PlCol=1:c; + obj.TCPlot={subplot(r,1,floor(r/2))}; + end + [x,y]=ndgrid(PlRow,PlCol); + x=transpose(x); + y=transpose(y); + for k=1:obj.NPlots + p=(x(k)-1)*c+y(k); + obj.SLPlot{k}=subplot(r,c,p); + end + end + + function PlotTimeCourse(obj,IC) + if isempty(obj.TimeCourseData) + id = 'GiftIcaReport:PlotTC:NoDataToPlot'; + msg = 'No time data to plot'; + throw(MException(id,msg)); + end + if IC>size(obj.TimeCourseData,2) + id = 'GiftIcaReport:PlotTC:InvalidComponent'; + msg = 'invalid component'; + throw(MException(id,msg)); + end + axes(obj.TCPlot{1}); + plot(obj.TimeCourseData(:,IC)); + end + + function PlotSlices(obj,IC) + if isempty(obj.ImageData) + id = 'GiftIcaReport:PlotTC:NoDataToPlot'; + msg = 'No time data to plot'; + throw(MException(id,msg)); + end + if IC>size(obj.ImageData,4) + id = 'GiftIcaReport:PlotTC:InvalidComponent'; + msg = 'invalid component'; + throw(MException(id,msg)); + end + for k=1:obj.NPlots + axes(obj.SLPlot{k}); %#ok + switch lower(obj.Orientation) + case 'cor' + if obj.PlotSliceNumbers(k)>size(obj.ImageData,2);continue;end + im=squeeze(obj.ImageData(:,obj.PlotSliceNumbers(k),:,IC)); + case 'tra' + if obj.PlotSliceNumbers(k)>size(obj.ImageData,3);continue;end + im=squeeze(obj.ImageData(:,:,obj.PlotSliceNumbers(k),IC)); + case 'sag' + if obj.PlotSliceNumbers(k)>size(obj.ImageData,1);continue;end + im=squeeze(obj.ImageData(obj.PlotSliceNumbers(k),:,:,IC)); + case 'all' + end + imagesc(im,obj.CLim); + camroll(90) + colormap(obj.Colormap); + axis image + axis off + end + end + + function GenReport(obj) + % load all info if not already present + if isempty(obj.ImageData)||isempty(obj.TimeCourseData) + obj.LoadData; + end + obj.BuildFigure; + % loop over IC + for IC=1:size(obj.TimeCourseData,2) + obj.PlotTimeCourse(IC); + obj.PlotSlices(IC); + obj.TCPlot{1}.Title.String= sprintf('IC:%.4d',IC); + [~,f,e]=fileparts(obj.FileOut); + switch lower(e) + case '.png' + fout=fullfile(obj.DirOut,sprintf('%s_%.4d.png',f,IC)); + type=-'png'; + otherwise + id = 'GiftIcaReport:GenReport:invalidFileType'; + msg = sprintf('Filetype not implemented'); + throw(MException(id,msg)); + end + saveas(gcf,fout,type); + end + %% this block of code gives a licence error. weird as I could create the object ? + % if isempty(obj.ReportObj) + % id = 'GiftIcaReport:GenReport:EmptyReportObject'; + % msg = 'No report object set in constructor of this object'; + % throw(MException(id,msg)); + % end + % if ~isa(obj.ReportObj,'mlreportgen.report.Report') + % id = 'GiftIcaReport:GenReport:WrongClassReportObject'; + % msg = 'No report object set in constructor of this object'; + % throw(MException(id,msg)); + % end + % import mlreportgen.report.* + % %open(obj.ReportObj) + % % generate the figure + % surf(peaks) %just for testing + % add(obj.ReportObj,Figure) + % %close(obj.ReportObj) + % disp(obj.ReportObj) + %% end end methods %private methods - function out = setfile(~,val) - if isempty(val) + function [nrow,ncol]=getrowcol(obj) + p=factor(obj.NPlots); + while numel(p)>2 + p(1)=p(1)*p(end); + p(end)=[]; + p=sort(p); + end + if numel(p)==1 % catch primes + p(2)=1; + p=sort(p); + end + if 9*p(2)>16*p(1) %very elongated plot + ncol=ceil(sqrt(obj.NPlots)); + nrow=ceil(obj.NPlots/ncol); + else + nrow=p(1); + ncol=p(2); + end + end + + function out = setfile(~,val) + if isempty(val) out={}; return end @@ -98,7 +384,7 @@ classdef GiftIcaReport