% STD_PLODTMAT - plot design matrix and info associated with the study for % each subject. Designed to be used directly (as a callback % function of button plot) from pop_studydesign % Usage: % >> std_plotdmat(STUDY.design(1),STUDY.datasetinfo) % % Inputs: % datasetinfo - datasetinfo % design - Structure with the fields {name,filepath,variable, % cases, include, deletepreviousfiles} for each variable % in the design. i.e. STUDY.design(1) % % Outputs: % % See also: % pop_studydesign % % Author: Ramon Martinez-Cancino & Arnaud Delorme, SCCN, 2014 % % Copyright (C) 2014 Ramon Martinez-Cancino, % % This file is part of EEGLAB, see http://www.eeglab.org % for the documentation and details. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % 1. Redistributions of source code must retain the above copyright notice, % this list of conditions and the following disclaimer. % % 2. Redistributions in binary form must reproduce the above copyright notice, % this list of conditions and the following disclaimer in the documentation % and/or other materials provided with the distribution. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF % THE POSSIBILITY OF SUCH DAMAGE. function std_plotmat(design,datasetinfo) % Set var stuff listsubj = unique(design.cases.value,'sorted'); % assuming cases.value will be always the subjects varindx = 1:length(design.variable); % checking if 'group' var (temporal commit to detect group vars, right now only detecting variable 'group') groupindx = find(strcmp({design.variable.label},'group')); if ~isempty(groupindx) varindx(groupindx) = []; end flag.dmatextend = true; flag.textdisp = 1; flag.subj = 1; setappdata(0,'flag',flag); handles.figmode = 0; % Change to 1 if info in GUI. 0 -> info in commandline % Creating GUI % Positions and settings %-------------------------------------------------------------------------- mainfig_pos = [.509 .465 .306 .519]; Text1_pos = [.120 .946 .191 .030]; Text2_pos = [.080 .208 .432 .029]; Text3_pos = [.397 .855 .24 .024]; Text4_pos = [.680 .946 .201 .030]; Text5_pos = [.380 .946 .201 .030]; checkbox_sort_pos = [.422 .896 .242 .035]; popup_subject_pos = [.124 .896 .224 .035]; disp_click_pos = [.7 .896 .183 .035]; if handles.figmode axes_pos = [.118 .306 .817 .513]; listbox1_pos = [.12 .018 .817 .178]; else axes_pos = [.118 .1 .817 .650]; end GUI_FONTSIZE = 12; AXES_FONTSIZE = 12; COLOR = [.66 .76 1]; figunits = 'Normalized'; % Main fig %-------------------------------------------------------------------------- handles.mainfig = figure('MenuBar' ,'none',... 'Name' ,['Design Matrix: ' design.name],... 'NumberTitle' ,'off',... 'Units' ,figunits,... 'Color' ,COLOR,... 'Position' ,mainfig_pos,... 'Visible' ,'off'); % Data in mainfig setappdata(handles.mainfig,'design',design); setappdata(handles.mainfig,'flag',flag); setappdata(handles.mainfig,'datasetinfo',datasetinfo); % Edit %-------------------------------------------------------------------------- if handles.figmode handles.disp_prop = uicontrol('Style','Edit'); set(handles.disp_prop,'String' ,'Loading..',... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,figunits,... 'BackgroundColor' ,COLOR,... 'Enable' ,'inactive',... 'Min' ,1,... 'Max' ,30,... 'Position' ,listbox1_pos); end handles.edit_dispclick = uicontrol('Style','Edit'); set(handles.edit_dispclick,'String' ,' ',... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,'Normalized',... 'enable' ,'off',... 'ForegroundColor' , [1 1 1],... 'BackgroundColor' ,[0 0 0],... 'Position' ,disp_click_pos); % Axes %-------------------------------------------------------------------------- handles.axes1 = axes('unit', 'normalized', 'position', axes_pos); handles.axes2 = axes('unit' ,'normalized', ... 'Position' ,axes_pos, ... 'XAxisLocation' ,'top',... 'YAxisLocation' ,'right',... 'Color' ,'none',... 'YTick' ,[],... 'YTickLabel' ,''); % Popupmenu %-------------------------------------------------------------------------- handles.popup_sort = uicontrol('Style','Popupmenu'); handles.popup_subject = uicontrol('Style','Popupmenu'); set(handles.popup_sort,'String' ,'',... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,figunits,... 'Position' ,checkbox_sort_pos,... 'callback' ,{@callback_popup_subject,handles}); set(handles.popup_subject,'String' ,listsubj,... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,figunits,... 'Position' ,popup_subject_pos,... 'callback' ,{@callback_popup_subject,handles}); callback_popup_subject('', '', handles); set(handles.mainfig, 'visible','on'); axes(handles.axes1); % Text %-------------------------------------------------------------------------- handles.Text1 = uicontrol('Style','Text'); set(handles.Text1,'String' ,'Select subject',... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,figunits,... 'BackgroundColor' ,COLOR,... 'Position' ,Text1_pos); if handles.figmode handles.Text2 = uicontrol('Style','Text'); set(handles.Text2,'String' ,'Subject Variables Design',... 'FontSize' ,GUI_FONTSIZE,... 'FontWeight' ,'bold',... 'Units' ,figunits,... 'BackgroundColor' ,COLOR,... 'Position' ,Text2_pos); end % handles.Text3 = uicontrol('Style','Text'); % set(handles.Text3,'String' ,'Design Matrix',... % 'FontSize' ,GUI_FONTSIZE+4,... % 'FontWeight' ,'bold',... % 'Units' ,figunits,... % 'BackgroundColor' ,COLOR,... % 'Position' ,Text3_pos); handles.Text4 = uicontrol('Style','Text'); set(handles.Text4,'String' ,'Value on Click',... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,figunits,... 'BackgroundColor' ,COLOR,... 'Position' ,Text4_pos); handles.Text5 = uicontrol('Style','Text'); set(handles.Text5,'String' ,'Sort by: ',... 'FontSize' ,GUI_FONTSIZE,... 'Units' ,figunits,... 'BackgroundColor' ,COLOR,... 'Position' ,Text5_pos); %-------------------------------------------------------------------------- % Callbacks %-------------------------------------------------------------------------- function callback_popup_subject(src,eventdata,handles) AXES_FONTSIZE = 11; design = getappdata(handles.mainfig,'design'); flag = getappdata(handles.mainfig,'flag'); datasetinfo = getappdata(handles.mainfig,'datasetinfo'); set(handles.edit_dispclick, 'String', ' ', ... 'ForegroundColor' , [1 1 1]); listsubj = unique(design.cases.value,'sorted'); % assuming cases.value will be always the subjects if isfield(handles,'popup_subject') indtmp = get(handles.popup_subject, 'Value'); else indtmp = 1; end inner_subj_flag = 1; if flag.subj ~= indtmp flag.textdisp = 1; flag.subj = indtmp; inner_subj_flag = 0; end subj = listsubj{indtmp}; % Retrieving all trials and values for this subject dsetinfo_subjindx = sort(find(strcmp({datasetinfo.subject},subj))); % in datasetinfo trialinfo = std_combtrialinfo(datasetinfo, dsetinfo_subjindx); % Combining trialinfo ntrials = 0; for i = 1 : length(dsetinfo_subjindx) startendindx(i,1) = ntrials + 1; ntrials = ntrials + length(datasetinfo(dsetinfo_subjindx(i)).trialinfo); startendindx(i,2) = ntrials; end % call function to build design matrix [tmpdmat,allLabels,catflag] = std_builddesignmat(design, trialinfo, flag.dmatextend); set(handles.popup_sort,'String' , [ ' ' allLabels ] ); % Removing NANs (Thanks Cyril!!!) check = find(sum(isnan(tmpdmat),2)); tmpdmat(check,:) = []; % Checking checkbox to sort/unsort dmatsortindex = 1:size(tmpdmat, 1); if get(handles.popup_sort, 'Value') ~= 1 [tmp,dmatsortindex] = sortrows(tmpdmat,get(handles.popup_sort, 'Value')-1); if inner_subj_flag, flag.textdisp = 0; end end % Updating the design info text2display(1) = {['Design Name: ' design.name]}; %Name of the design % Name and values of Regressors for i = 1:length(design.variable) % Loop per condition allvarstmp = '['; for j = 1 : length(design.variable(i).value) % allvarstmp = [allvarstmp ' ' num2str(design.variable(i).value{j})]; % -- if ischar(design.variable(i).value{j}) allvarstmp = [allvarstmp ' ' design.variable(i).value{j}]; elseif iscell(design.variable(i).value{j}) % Concat all vals varnametmp = design.variable(i).value{j}{1}; for ivar = 2: length(design.variable(i).value{j}) varnametmp = [varnametmp '&' design.variable(i).value{j}{ivar}]; end allvarstmp = [allvarstmp ' ' varnametmp]; elseif isnumeric(design.variable(i).value{j}) allvarstmp = [allvarstmp ' ' int2str(design.variable(i).value{j})]; end % -- end allvarstmp = [allvarstmp ' ]']; ncond(i) = length(design.variable(i).value); text2display(2*i) = {['Regressor ' num2str(i) ' : ' design.variable(i).label]}; text2display(2*i + 1) = {['Regressor ' num2str(i) ' values :' allvarstmp]}; end text2display(2*(i+1)) = {['Regressor ' num2str(i+1) ' : Baseline' ]}; text2display(2*(i+1) + 1) = {['Regressor ' num2str(i+1) ' values : [1]' ]}; % Display values if handles.figmode set(handles.disp_prop,'String',text2display,'HorizontalAlignment', 'left','FontSize', AXES_FONTSIZE); elseif flag.textdisp display('----------------------------------------') display(['--- Subject ' subj ' Variables Design---']) disp(text2display(:)); display('----------------------------------------') handles.notdisp = 0; end % Normalizing tmpdmat for plot normtmpdmat = nan(size(tmpdmat)); for iCol = 1:size(tmpdmat,2) dmat_den = (max(tmpdmat(:,iCol))-min(tmpdmat(:,iCol))); if length(unique(tmpdmat(:,iCol))) <= 2, tmpdmat(:,iCol) = ~tmpdmat(:,iCol); end % flip colors if dmat_den ~= 0 normtmpdmat(:,iCol) = (tmpdmat(:,iCol)-min(tmpdmat(:,iCol)))/dmat_den; else normtmpdmat(:,iCol) = deal(max(tmpdmat(:,iCol))); end end % Plot matrix set(handles.mainfig,'CurrentAxes',handles.axes1); handles.figure = imagesc(normtmpdmat(dmatsortindex,:)); colormap(flipud(colormap('gray'))); xlabel('Regressors',... 'FontWeight', 'normal',... 'FontSize', AXES_FONTSIZE+4); ylabel('Trials',... 'FontWeight', 'Normal',... 'FontSize', AXES_FONTSIZE+4); set(handles.axes1,'XTick',1:size(tmpdmat,2)) set(handles.axes2','XTick' ,get(handles.axes1, 'XTick'),... 'XTickLabel', allLabels,... 'xticklabelrotation', 15,... 'XLim' , get(handles.axes1, 'XLim'),... 'FontSize' , AXES_FONTSIZE+2); set(handles.axes1,'FontSize', AXES_FONTSIZE+2) set(handles.figure, 'ButtonDownFcn', {@callback_dmatclick,handles,tmpdmat(dmatsortindex,:),design}); setappdata(handles.mainfig,'flag',flag); drawnow; %-------------------------------------------------------------------------- function callback_dmatclick(src,eventdata,handles,tmpdmat,design) axesHandle = get(src,'Parent'); coordinates = get(axesHandle,'CurrentPoint'); coordinates = round(coordinates(1,1:2)); tmpdmatval = tmpdmat(coordinates(2), coordinates(1)); flag = getappdata(handles.mainfig,'flag'); if flag.dmatextend && coordinates(1) <= size(tmpdmat,2)-1 for i = 1:length(design.variable) nvars = numel(design.variable(i).value); if nvars == 0, nvars = 1; end reg_varind_tmp{i} = ones(1,nvars)*i; end reg_varind = cell2mat(reg_varind_tmp); indx1 = reg_varind(coordinates(1)); else indx1 = coordinates(1); end if coordinates(1) <= size(tmpdmat,2)-1 if isfield(design.variable(indx1),'vartype') && strcmp(design.variable(indx1).vartype, 'categorical') if ~flag.dmatextend val = design.variable(indx1).value(tmpdmatval); else val = tmpdmatval; end else % Note: When an old STUDY is used without modifying the variables, % the structure 'STUDY.design' does not have the field 'vartype'. val = tmpdmatval; end else val = 1; end if isnumeric(val) val = num2str(val); end set(handles.edit_dispclick, 'String', val, ... 'ForegroundColor' , [0 0 0]);