%qsubfunc() - submit a job to the SGE queue system, % version 1.00, 25 Oct 2002 % % Usage: % >> qsubfunc( funcname, funcarg); % >> status = qsubfunc( funcname, funcarg, funcout, 'key', 'val' ); % >> status = qsubfunc({{ funcname1, funcarg1, funcout1, 'key', 'val' ... } ... % { funcname2, funcarg2, funcout2, 'key', 'val' ... }}); % % Inputs: % funcname - string for the function name. Can also be a cell array % of cell array of calls to qsubfunc (see example). % funcarg - cell array of the function arguments % funcout - cell array of output variables in the global % worspace (strings). Default is []. % % Optional inputs: % 'display' - ['on'|'off'] send back display to original % X window server. Default is 'on'. % 'jobname' - ['string'] name for the job. Default is % 'qsub[funcname][XXXX]' where XXXX is a random number % 'mail' - ['on'|'off'] send mail for job events (job beginning, ... % end, abord, suspend). Default is 'off'. % 'mailabord' - ['on'|'off'] send mail only for job problems such as % when the job is aborded or suspended. Default is 'on'. % 'nice' - [integer] renice the job. Default is -15. % 'comsave' - [command] instead of displaying the figure, the % 'comsave' command is executed. Note that this can be % use in conjunction with 'display'. By default when % the 'comsave' command is not empty, the 'display' is % set to 'off', but you might force it to 'on' to save 'jpg' % figures for instance which requires the X-SERVER to be % functional (not required for printing 'eps' files or for % using the hgsave() function). % Ex: 'print -depsc /home/user/test.eps' % 'processes - Cell array of other parrallel function to launch. The % syntax is the same as the qsubfunction. This is only % usefull if the called functions return some values % (otherwise it is possible to launch all the commands % sequentially). % % Outputs: status - [0|1] 0=fail, 1=suceeded to submit job % % Example: % % % submit a single plotting job % qsubfunc('plot', { [0:10] }); % % % submit 4 plotting jobs and returns % qsubfunc({{'plot', { [0:10] 'r' }}, { 'plot', { [10:20] 'm' } } ... % { 'plot', { [20:30] 'g' } } { 'plot', { [30:40] 'y' } }} ); % % % submit 2 compute jobs and pops-up an editing window % % to enter commands in the local workspace while the jobs are running % qsubfunc({ {'max', { [1:10,11:-1:1] }, { 'maxval' 'maxindex' }} ... % {'min', { [1:10,11:-1:1] }, { 'minval' 'minindex' }}} ); % % the two jobs are strickly equivalent to the evaluation of the % % following expression in the global workspace % [maxval maxindex] = max([1:10,11:-1:1]); % [minval minindex] = min([1:10,11:-1:1]); % % Note: % The qsubfunc will create a directory name "qsub" in your home direcoty, % then create sub-folder in this directory (these folders may have to be % removed manually). % Recursive call the qsubfunc from the qsubfunc edit window are possible. % % Graphical interface: % Exectute a command: when jobs returns values to the global workspace, % qsubfunc() have to wait for them (to write a file) and an editing % window pops-up for the user to enter local commands to execture. To % execute a command, type in some text and press the "Exectute button". % Abord computation: it is also possible to abord in the computation local % Matlab session by pressing the abord button (note that jobs sent to the % grid are not automatically killed and have to be killed manually using % qdel under unix). % Close window: when computation is finished, the Abord button becomes % inactivated and the "Ready to close" button become activated. The window % does not close automatically as the user could be editing some text. % % Troubleshooting: % The function has been tested on Matlab 6.1 under Redhat Linux 2.4.19 % using Sun Grid Engine 5.2 and tcsh shell. % 1) Problems may arise with use of bash. % 2) Check that the nice command is accessible in /bin/nice otherwise % edit the code and enter the location of the nice command (or simply % "nice"). % 3) For any other problem, contact arno@salk.edu with a detailed % description of the problem. % % Version: % The atest version of the program is available at % www.sccn.ucsd.edu/~arno/qsubfunc/qsubfunc.php % % Authors: Arnaud Delorme, CNL / Salk Institute, 11 Oct 2002 % (Joern Anemuller for the unix qsub call syntax) % % See also: eeglab() %123456789012345678901234567890123456789012345678901234567890123456789012 % Copyright (C) 2002 Arnaud Delorme & Jorn Anemuller, Salk Institute, arno@salk.edu % % 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 % $Log: qsubfunc.m,v $ % Revision 1.19 2002/10/25 16:41:51 arno % add quesdlg2 and more doc % % Revision 1.18 2002/10/25 01:59:33 arno % adding finputcheck code % % Revision 1.17 2002/10/25 01:55:47 arno % including supergui in qsubfunc % % Revision 1.16 2002/10/25 00:41:34 arno % nice update % % Revision 1.15 2002/10/25 00:35:14 arno % debug command call % % Revision 1.14 2002/10/25 00:32:14 arno % job index corrected % % Revision 1.13 2002/10/25 00:28:10 arno % more debuging % % Revision 1.12 2002/10/25 00:20:43 arno % update qsubfunc for real parallel processing % % Revision 1.11 2002/10/24 22:18:44 arno % remove directory % % Revision 1.10 2002/10/24 20:13:40 arno % remove comment % % Revision 1.9 2002/10/24 20:12:47 arno % new qsubfunc mutiprocess % % Revision 1.8 2002/10/21 18:52:17 arno % nice update % % Revision 1.7 2002/10/21 17:30:57 arno % reset random generator % % Revision 1.6 2002/10/14 01:05:40 arno % xhost + % % Revision 1.5 2002/10/13 23:26:17 arno % putting path to the UNIX call % % Revision 1.4 2002/10/11 18:14:59 arno % new options % % Revision 1.3 2002/10/11 17:26:37 arno % debugging display % % Revision 1.2 2002/10/11 17:05:49 arno % real intial revision % % note for how to return values % I looked thrgh all the documentation, etc and there is 2 solutions % 1 - write my own editor, so that the user is still able to evaluate expressions. % I can make a simple edit box and scroll the text up dan down, while using % the global workspace. % 2 - start asynchronously mex commands function status = qsubfunc( funcname, funcarg, funcout, varargin ); status = 0; if nargin < 1 help qsubfunc; return; end; if nargin < 2 funcarg = {}; end; if nargin < 3 funcout = {}; end; if iscell(funcname) qsubfunc(funcname{1}{:}, 'processes', funcname(2:end)); return; end; % check inputs % ------------ g = finputcheck(varargin, { 'display' 'string' { 'on' 'off' } 'on'; ... 'jobname' 'string' [] ''; ... 'mail' 'string' { 'on' 'off' } 'off'; ... 'jobindex' 'integer' [] 1; ... 'nice' 'integer' [] -15; ... 'mailabord' 'string' { 'on' 'off' } 'on'; ... 'processes' 'cell' [] {}; ... 'comsave' 'string' [] ''}, 'qsubfunc'); if isstr(g), error(g); end; if isempty(g.jobname) g.jobname = sprintf('qsub%s%5.5d', funcname, floor(rand*100000)); end; rand('state',sum(100*clock)); if ~isstr(funcname) disp('Error qsubfunc arguments: funcname must be a string, call aborded'); return; end; if ~isempty(funcarg) if ~iscell(funcout) disp('Error qsubfunc arguments: funcarg must be a cell array, call aborded'); return; end; end; if ~isempty(funcout) if ~iscell(funcout) disp('Error qsubfunc arguments: funcout must be a cell array, call aborded'); return; else for index = 1:length(funcout) if ~isstr(funcout{index}) disp('Error qsubfunc arguments: funcout must be a cell array of strings, call aborded'); return; end; end; end; end; % copy param file to directory % ---------------------------- oldd = pwd; cd ~ [res tmp] = mkdir('qsub'); cd qsub count = 10; res = 0; fprintf('********************** Processing job %d ***********************\n', g.jobindex); while res ~= 1 | count == 0 fprintf('Atempting to create directory ''%s'': ', g.jobname); [res tmp] = mkdir(g.jobname); if res ~= 1, fprintf('failure\n'); g.jobname = sprintf('qsub%s%5.5d', funcname, floor(rand*100000)); else fprintf('OK\n'); cd(g.jobname); end; coutn = count-1; end; if count == 0, cd(olld); error('Can not create new directory'); end; save('funcarg.mat', '-mat', 'funcarg'); % prepare function outputs % ------------------------ argsout = ''; saveout = ''; for index = 1:length(funcout) argsout = [ argsout ' out' int2str(index) ]; saveout = [ saveout '''out' int2str(index) ''',']; end; if ~isempty(argsout), argsout = [ '[' argsout '] =' ]; end; % make and execute command % ------------------------ matlabcom = [ 'load(''funcarg.mat'');' ... 'lasterr(''''); try,' argsout funcname '(funcarg{:}); lasterr(''''); catch, end;']; [tmp hostname] = unix('hostname'); matlabopt = '-nosplash -nodesktop'; if strcmpi(g.display, 'off') matlabopt = [ matlabopt ' -nodisplay' ]; else if g.jobindex == 1 unix('xhost +'); end; if isempty(g.comsave) matlabcom =[matlabcom 'if ~isempty(get(0, ''currentfigure'')); waitfor(gcf); end;' ]; end; end; if ~isempty(argsout) matlabcom = [ matlabcom 'funcerr = lasterr; if isempty(funcerr), save(''funcout.mat'', ''-mat'',' saveout ' ''funcerr'');' ... 'else, save(''funcout.mat'', ''funcerr''); end;' ]; end; matlabcom =[matlabcom g.comsave ]; unixcom = [ 'setenv DISPLAY ' hostname(1:end-1) ':0.0;' ... 'cd qsub/' g.jobname ';' ... '/bin/nice ' int2str(g.nice) ' matlab ' ... matlabopt ' -r \042' matlabcom '\042;']; if isempty(funcout) unixcom = [ unixcom 'cd ..;rm -f -r ' g.jobname]; end; if strcmp(g.mail, 'on'), qsubopt = '-m beas'; elseif strcmp(g.mailabord, 'on'), qsubopt = '-m as'; else qsubopt =''; end; strCmd = ['echo "' unixcom '" | qsub ' qsubopt ' -soft -l mem_total=3.5G,speed=1700 -N "' g.jobname '"']; %fprintf('Executing command:\n%s\n\n', strCmd); unix(strCmd); % create editing window % --------------------- windowcreator = 0; fig = findobj('tag', 'qsubfunc'); if isempty(fig) fig = figure('visible', 'off', 'tag', 'qsubfunc', 'userdata', []); abordcom = [ 'if strcmpi(questdlg2(''All pending data will be lost'', ''Cancel'', ''Ok'', ''Ok''), ''ok''),' ... 'set(gcbf, ''userdata'', -1); end;' ]; execcom = [ 'disp(get(findobj(gcbf, ''tag'', ''strcommand''), ''string''));' ... 'evalin(''base'', get(findobj(gcbf, ''tag'', ''strcommand''), ''string''), ''disp(lasterr);''); drawnow;']; supergui( fig, [1 1 1 3], [1 4 1 1], {'style' 'text' 'string', 'Enter matlab command below ' }, ... {'style' 'edit' 'string', '', 'tag', 'strcommand', 'HorizontalAlignment', 'left' }, ... {'style' 'text' 'string', 'Job running (only includes job returning outputs): 1', 'tag', 'jobrun' }, ... {'style' 'pushbutton' 'string', 'Abord', 'tag', 'abord', 'callback', abordcom }, ... {'style' 'pushbutton' 'string', 'Ready to close', 'tag', 'close', 'enable', 'off', 'callback', 'close(gcbf);' }, ... {'style' 'pushbutton' 'string', 'Execute', 'callback', execcom } ); set(gcf, 'visible', 'off'); windowcreator = 1; else objjob = findobj(fig, 'tag', 'jobrun'); curjobs = get(fig, 'userdata'); if length(curjobs) == 0 windowcreator = 1; end; end; if ~isempty(funcout) curjobs = get(fig, 'userdata'); curjobs(end+1).proc = g.jobindex; curjobs(end).folder = g.jobname; curjobs(end).funcout = funcout; set(fig, 'userdata', curjobs); objjob = findobj(fig, 'tag', 'jobrun'); set(objjob, 'string', ['Job running (only includes job returning outputs): ' , int2str(length(curjobs)) ] ); drawnow; set(findobj(fig, 'tag', 'abord'), 'enable', 'on'); set(findobj(fig, 'tag', 'close'), 'enable', 'off'); % do not allow window to close end; % deal with other processes to launch % ----------------------------------- if ~isempty(g.processes) cd(oldd); for index = 1:length(g.processes) qsubfunc(g.processes{index}{:}, 'jobindex', g.jobindex+index); end; end; % waiting for outputs and processing them % --------------------------------------- if windowcreator fig = findobj('tag', 'qsubfunc'); pendingjobs = length(get(fig, 'userdata')); if pendingjobs == 0 cleanup; return; else set(fig, 'visible', 'on'); drawnow; end; cd('~/qsub'); while length(pendingjobs) > 0 pause(0.5); pendingjobs = get(fig, 'userdata'); if ~isstruct(pendingjobs) % abord close(fig); disp('Warning: jobs might still be running on other machines'); pendingjobs = []; end; index = 1; while index <= length(pendingjobs) if exist([ pendingjobs(index).folder '/funcout.mat' ]) % reading outputs to global workspace % ----------------------------------- evalin('base', [ 'load(''' pendingjobs(index).folder '/funcout.mat'');' ]); unix(['rm -f -r ' pendingjobs(index).folder ]); if evalin('base', '~isempty(funcerr)') evalin('base', 'funcerr = sprintf(''\nError while calling process using qsub:\n\n%s'', funcerr); disp(funcerr);'); else funcout = pendingjobs(index).funcout; fprintf('Process %d: Loading ''%s'' function return variables ''%s'' ...\n', pendingjobs(index).proc, funcname, funcout{1}); for indexout = 1:length(funcout) evalin('base', [ funcout{indexout} ' = out' int2str(indexout) ';' ], 'disp(lasterr);'); evalin('base' , ['clear out' int2str(indexout) ]); warning on; end; end; evalin('base', 'clear funcerr;'); % update gui window % ----------------- pendingjobs(index) = []; set(fig, 'userdata', pendingjobs); objjob = findobj(fig, 'tag', 'jobrun'); set(objjob, 'string', ['Jobs running (only includes jobs returning outputs): ' int2str(length(pendingjobs))] ); drawnow; end; index = index + 1; end; end; % end while cleanup; end; cd(oldd); status = 1; return; function cleanup; fig = findobj('tag', 'qsubfunc'); if ~isempty(fig) set(findobj(fig, 'tag', 'abord'), 'enable', 'off'); % allow window to close set(findobj(fig, 'tag', 'close'), 'enable', 'on'); % allow window to close end; % questdlg2() - questdlg function clone with coloring and help for % eeglab(). % % Usage: same as questdlg() % % Warning: % Case of button text and result might be changed by the function % % % Author: Arnaud Delorme, CNL / Salk Institute, La Jolla, 11 August 2002 % % See also: inputdlg2(), errordlg2(), supergui(), inputgui() %123456789012345678901234567890123456789012345678901234567890123456789012 % Copyright (C) Arnaud Delorme, CNL / Salk Institute, arno@salk.edu % % 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 % $Log: qsubfunc.m,v $ % Revision 1.19 2002/10/25 16:41:51 arno % add quesdlg2 and more doc % % Revision 1.11 2002/10/15 17:23:50 arno % drawnow % % Revision 1.10 2002/10/15 16:54:09 arno % add drawnow ofr windows % % Revision 1.9 2002/10/15 14:45:12 arno % display warning % % Revision 1.8 2002/10/15 14:35:52 arno % default case for buttons % % Revision 1.7 2002/08/14 18:17:00 arno % new supergui arg % % Revision 1.6 2002/08/13 22:36:43 arno % debug for error % % Revision 1.5 2002/08/13 17:29:35 arno % new superguicall % % Revision 1.4 2002/08/12 18:49:20 arno % header % % Revision 1.3 2002/08/12 18:24:29 arno % debug % % Revision 1.2 2002/08/12 18:02:47 arno % debug % % Revision 1.1 2002/08/12 18:01:34 arno % Initial revision % function [result] = questdlg2(Prompt,Title,varargin); result = varargin{end}; if nargin < 2 help questdlg2; return; end; if Prompt(end) == 10, Prompt(end) = []; end; if Prompt(end) == 10, Prompt(end) = []; end; if Prompt(end) == 10, Prompt(end) = []; end; if Prompt(end) == 10, Prompt(end) = []; end; fig = figure('visible', 'off'); set(gcf, 'name', Title); geometry = {[1]}; listui = {{ 'Style', 'text', 'string' Prompt }}; geometry = { geometry{:} ones(1,length(varargin)-1) }; for index = 1:length(varargin)-1 % ignoring default val listui = {listui{:} { 'Style', 'pushbutton', 'string', varargin{index}, 'callback', ['set(gcbf, ''userdata'', ''' varargin{index} ''');'] } }; if strcmp(varargin{index}, varargin{end}) listui{end}{end+1} = 'fontweight'; listui{end}{end+1} = 'bold'; end; end; cr = length(find(Prompt == char(10)))+1; if cr == 1 cr = size(Prompt,1); end; [tmp tmp2 allobj] = supergui( fig, geometry, [cr 1], listui{:} ); waitfor( fig, 'userdata'); try, result = get(fig, 'userdata'); close(fig); drawnow; end; % supergui() - a comprehensive gui automatic builder. This function help % to create GUI very fast without bothering about the % positions of the elements. After creating a geometry, % elements just place themselves into the predefined % locations. It is especially usefull for figure where you % intend to put text button and descriptions. % % Usage: % >> [handlers, width, height ] = ... % supergui( geomx, geomy, { arguments1 }, { arguments2 }... ); % % Inputs: % figh - figure handler, if 0 create a new figure % geomx - cell array describing the geometry of the elements % in the figure. For instance, [2 3 2] means that the % figures will have 3 rows, with 2 elements in the first % and last row and 3 elements in the second row. % An other syntax is { [2 8] [1 2 3] } which means % that figures will have 2 rows, the first one with 2 % elements of relative width 2 and 8 (20% and 80%). The % second row will have 3 elements of relative size 1, 2 % and 3. % geomy - [array] describting geometry for the rows. For instance % [1 2 1] means that the second row will be twice the height % of the other ones. If [], all the lines have the same height. % {argument} - GUI matlab element arguments. Ex { 'style', % 'radiobutton', 'String', 'hello' }. % % Hint: % use 'print -mfile filemane' to save a matlab file of the figure. % % Output: % handlers - all the handler of the elements (in the same form as the % geometry cell input. % height - adviced widht for the figure (so the text look nice). % height - adviced height for the figure (so the text look nice). % % Example: % figure; % supergui( [1 1], [], { 'style', 'radiobutton', 'string', 'radio' }, ... % { 'style', 'pushbutton', 'string', 'push' }); % % Author: Arnaud Delorme, CNL / Salk Institute, La Jolla, 2001 % % See also: eeglab() %123456789012345678901234567890123456789012345678901234567890123456789012 % Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu % % 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 % $Log: qsubfunc.m,v $ % Revision 1.19 2002/10/25 16:41:51 arno % add quesdlg2 and more doc % % Revision 1.18 2002/10/25 01:59:33 arno % adding finputcheck code % % Revision 1.17 2002/10/25 01:55:47 arno % including supergui in qsubfunc % % Revision 1.34 2002/10/23 15:06:40 arno % isppc -> computer % % Revision 1.33 2002/10/15 16:25:15 arno % magnify edit boxes windows % % Revision 1.32 2002/10/15 14:42:15 arno % button text aspect % % Revision 1.31 2002/08/20 22:33:34 arno % debug for Mac % % Revision 1.30 2002/08/19 19:12:16 arno % debugging last % % Revision 1.29 2002/08/19 19:10:13 arno % figure bigger for MAC % % Revision 1.28 2002/08/17 02:38:42 arno % debugging % % Revision 1.27 2002/08/14 18:17:23 arno % new supergui arg % % Revision 1.26 2002/08/14 18:07:20 arno % changing default checkbox backcolor % % Revision 1.25 2002/08/14 16:32:37 arno % yfact takes into account button now % % Revision 1.24 2002/08/13 23:04:51 arno % debug pop_merge % % Revision 1.23 2002/08/13 18:59:49 arno % update automatic INSETY % % Revision 1.22 2002/08/13 18:56:01 arno % adjustments % % Revision 1.21 2002/08/13 18:50:54 arno % same % % Revision 1.20 2002/08/13 18:50:31 arno % vert align % % Revision 1.19 2002/08/13 17:40:41 arno % same % % Revision 1.18 2002/08/13 17:38:13 arno % ordinate adjustment % % Revision 1.17 2002/08/13 17:28:56 arno % new geometry % % Revision 1.16 2002/08/13 00:20:42 arno % same % % Revision 1.15 2002/08/13 00:20:22 arno % update position % % Revision 1.14 2002/08/12 21:42:59 arno % ignore pushbutton extent % % Revision 1.13 2002/08/12 16:00:57 arno % same % % Revision 1.12 2002/08/12 16:00:13 arno % do not adapt size for edit windows % % Revision 1.11 2002/08/12 15:57:04 arno % size calculation % % Revision 1.10 2002/08/12 14:50:15 arno % color % % Revision 1.9 2002/08/12 14:47:40 arno % color % % Revision 1.8 2002/08/12 14:30:55 arno % background % % Revision 1.7 2002/08/12 01:17:42 arno % update colors % % Revision 1.6 2002/08/12 00:41:41 arno % updating default colors % % Revision 1.5 2002/07/18 17:18:31 arno % offscreen correction % % Revision 1.4 2002/07/18 17:13:05 arno % same % % Revision 1.3 2002/07/18 17:11:19 arno % correct out-of screen problem % % Revision 1.2 2002/07/18 17:07:40 arno % no modif % % Revision 1.1 2002/04/05 17:39:45 jorn % Initial revision % function [handlers, outheight, allhandlers] = supergui( fig, geomx, geomy, varargin); % handlers cell format % allhandlers linear format INSETX = 0.05; % x border absolute (5% of width) INSETY = 0.05/length(geomx); % y border relative (50% of heigth) if nargin < 2 help supergui; return; end; if fig == 0 figure('visible','off'); end; % converting the geometry formats % ------------------------------- if ~iscell( geomx ) oldgeom = geomx; geomx = {}; for row = 1:length(oldgeom) geomx = { geomx{:} ones(1, oldgeom(row)) }; end; end; if isempty(geomy) geomy = ones(1, length(geomx)); end; % setting relative width in percent % --------------------------------- for row = 1:length(geomx) tmprow = geomx{row}; sumrow = sum(geomx{row}); geomx{row} = 1.05*geomx{row}/sumrow; geomx{row} = geomx{row} - INSETX*(length(tmprow)-1)/length(tmprow); end; % setting relative height in percent % --------------------------------- sumcol = sum(geomy); geomy = (1.03+0.003*sumcol)*geomy/sumcol; geomy = geomy - INSETY*(length(geomy)-1)/length(geomy); % get axis coordinates % -------------------- set(gcf, 'menubar', 'none', 'numbertitle', 'off'); pos = get(gca,'position'); % plot relative to current axes q = [pos(1) pos(2) 0 0]; s = [pos(3) pos(4) pos(3) pos(4)]; % allow to use normalized position [0 100] for x and y axis('off'); % creating guis % ------------- counter = 1; % count the elements outwidth = 0; outheight = 0; %height = 1.05/(length(geomx)+1)*(1-INSETY); %posy = 1 - height - 1/length(geomx)*INSETY; factmultx = 0; factmulty = 0; %zeros(length(geomx)); posy = 0.98+(0.003*sumcol)/2+INSETY; for row = 1:length(geomx) % init posx = -0.05; clear rowhandle; tmprow = geomx{row}; height = geomy(row); posy = posy - height - INSETY; for column = 1:length(tmprow) width = tmprow(column); try currentelem = varargin{ counter }; catch fprintf('Warning: not all boxes were filled\n'); return; end; if ~isempty(currentelem) rowhandle(column) = uicontrol( 'unit', 'normalized', 'position', ... [posx posy width height].*s+q, currentelem{:}); % this simply compute a factor so that all uicontrol will be visible % ------------------------------------------------------------------ style = get( rowhandle(column), 'style'); set( rowhandle(column), 'units', 'pixels'); curpos = get(rowhandle(column), 'position'); curext = get(rowhandle(column), 'extent'); if ~strcmp(style, 'edit') & ~strcmp(style, 'pushbutton') factmultx = max(factmultx, curext(3)/curpos(3)); end; factmulty = max(factmulty, curext(4)/curpos(4)); set( rowhandle(column), 'units', 'normalized'); % Uniformize button text aspect % ----------------------------- if strcmp(style, 'pushbutton') tmptext = lower(get(rowhandle(column), 'string')); try, tmptext(1) = upper(tmptext(1)); catch, end; set(rowhandle(column), 'string', tmptext); end; else rowhandle(column) = 0; end; handlers{ row } = rowhandle; allhandlers(counter) = rowhandle(column); posx = posx + width + INSETX; counter = counter+1; end; %posy = posy - height - 1/length(geomx)*INSETY; %compensate for inset end; % adjustments % ----------- factmultx = factmultx+0.1; % because some text was still hidden if factmultx < 0.3 factmultx = 0.3; end; % for MAC (magnify figures that have edit fields) % ------- warning off; try, if strcmp(computer, 'MAC') hh = findobj(allhandlers, 'style', 'edit'); if ~isempty(hh) factmulty = factmulty*1.4; end; elseif ~isunix % windows hh = findobj(allhandlers, 'style', 'edit'); if ~isempty(hh) factmulty = factmulty*1.15; end; end; catch, end; warning on; % scale and replace the figure in the screen % ----------------------------------------- pos = get(gcf, 'position'); if factmulty > 1 pos(2) = max(0,pos(2)+pos(4)-pos(4)*factmulty); end; pos(1) = pos(1)+pos(3)*(1-factmultx)/2; pos(3) = pos(3)*factmultx; pos(4) = pos(4)*factmulty; set(gcf, 'position', pos); % vertical alignment to bottom for text % --------------------------------------- for index = 1:length(allhandlers) if allhandlers(index) ~= 0 if strcmp(get(allhandlers(index), 'style'), 'text') curpos = get(allhandlers(index), 'position'); curext = get(allhandlers(index), 'extent'); set(allhandlers(index), 'position',[curpos(1) curpos(2) curpos(3) curext(4)]); end; end; end; % setting defaults colors %------------------------ try, icadefs; catch, GUIBACKCOLOR = [.8 .8 .8]; GUIPOPBUTTONCOLOR = [.8 .8 .8]; GUITEXTCOLOR = [0 0 0]; end; hh = findobj(allhandlers, 'parent', gcf, 'style', 'text'); %set(hh, 'BackgroundColor', get(gcf, 'color'), 'horizontalalignment', 'left'); set(hh, 'Backgroundcolor', GUIBACKCOLOR); set(hh, 'foregroundcolor', GUITEXTCOLOR); set(gcf, 'color',GUIBACKCOLOR ); set(hh, 'horizontalalignment', 'left'); hh = findobj(allhandlers, 'style', 'edit'); set(hh, 'BackgroundColor', [1 1 1]); %, 'horizontalalignment', 'right'); hh =findobj(allhandlers, 'parent', gcf, 'style', 'pushbutton'); set(hh, 'backgroundcolor', GUIPOPBUTTONCOLOR); set(hh, 'foregroundcolor', GUITEXTCOLOR); hh =findobj(allhandlers, 'parent', gcf, 'style', 'checkbox'); if isunix set(hh, 'backgroundcolor', GUIPOPBUTTONCOLOR); set(hh, 'foregroundcolor', GUITEXTCOLOR); else set(hh, 'backgroundcolor', GUIBACKCOLOR); set(hh, 'foregroundcolor', GUITEXTCOLOR); end; hh =findobj(allhandlers, 'parent', gcf, 'style', 'listbox'); set(hh, 'backgroundcolor', GUIPOPBUTTONCOLOR); set(hh, 'foregroundcolor', GUITEXTCOLOR); hh =findobj(allhandlers, 'parent', gcf, 'style', 'radio'); set(hh, 'foregroundcolor', GUITEXTCOLOR); set(hh, 'backgroundcolor', GUIPOPBUTTONCOLOR); set(gcf, 'visible', 'on'); return;% finputcheck() - check matlab function { 'key', 'val' } inputs % % Usage: >> struct = finputcheck( varargin, fieldlist ); % >> [struct varargin] = finputcheck( varargin, fieldlist, ... % callingfunc, mode ); % % Input: % varargin - varargin arguement from a function call with 'key', 'val' % arguements. % fieldlist - 3 or 4 columns cell array with one row per variable. The first % column contain the variable name, the second one the type, % the third the accepted value range and the fourth one the % defaultvalue. Ex: % { 'varanme1' { 'value1' 'value2' } 'defaultvaluevar1' } % { 'varanme2' { int1 int2 } 'defaultvaluevar2' } % etc... % allowed types are 'boolean', 'integer', 'real', 'string', % 'cell' or 'struct' % the fifth column may contain the size (can be a cell array % of size), but is optional. % callingfunc - calling function name for error messages. Default is none. % mode - ['ignore'|'error'] ignore keywords that are not specified in % the fieldlist cell array or generate an error. Default is % 'error'. % Outputs: % struct - checked structure % varargin - residual varagin with non-recognized arguments % % Note: in case of error, a string is returned with the error message % instead of a structure. % % Example: % finputcheck(varargin, % { 'title' 'string' [] ''; % 'percent' 'real' [0 1] 1 ; % 'elecamp' 'integer' [1:10] [] }); % 'title' is a string with no default value % 'percent' is a real number in between 0 and 1 and default value 1 % 'elecamp' is an integer that can tak value between 1 and 10 % % Author: Arnaud Delorme, CNL / Salk Institute, 10 July 2002 %123456789012345678901234567890123456789012345678901234567890123456789012 % Copyright (C) Arnaud Delorme, CNL / Salk Institute, 10 July 2002, arno@salk.edu % % 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 % $Log: qsubfunc.m,v $ % Revision 1.19 2002/10/25 16:41:51 arno % add quesdlg2 and more doc % % Revision 1.18 2002/10/25 01:59:33 arno % adding finputcheck code % % Revision 1.11 2002/09/30 15:29:23 arno % autorizing cell arrays for types % % Revision 1.10 2002/09/30 00:42:08 arno % debug input arguments % % Revision 1.9 2002/07/29 18:00:53 arno % debugging for NaN % % Revision 1.8 2002/07/29 17:24:22 arno % header % % Revision 1.7 2002/07/20 19:10:41 arno % debugging output % % Revision 1.6 2002/07/19 17:58:11 arno % returning non-matched 'key' 'val' arguments % % Revision 1.5 2002/07/19 17:46:53 arno % g empty if no varargin % % Revision 1.4 2002/07/19 16:27:14 arno % adding ignore mode % % Revision 1.3 2002/07/10 02:18:32 arno % header info % % Revision 1.2 2002/07/10 02:17:27 arno % debugging error message passing % % Revision 1.1 2002/07/10 01:03:19 arno % Initial revision % function [g, varargnew] = finputcheck( vararg, fieldlist, callfunc, mode ) if nargin < 2 help finputcheck; return; end; if nargin < 3 callfunc = ''; else callfunc = [callfunc ' ' ]; end; if nargin < 4 mode = 'do not ignore'; end; NAME = 1; TYPE = 2; VALS = 3; DEF = 4; SIZE = 5; varargnew = {}; % create structure % ---------------- if ~isempty(vararg) for index=1:length(vararg) if iscell(vararg{index}) vararg{index} = {vararg{index}}; end; end; try g = struct(vararg{:}); catch g = [ callfunc 'error: bad ''key'', ''val'' sequence' ]; return; end; else g = []; end; for index = 1:size(fieldlist,NAME) % check if present % ---------------- if ~isfield(g, fieldlist{index, NAME}) g = setfield( g, fieldlist{index, NAME}, fieldlist{index, DEF}); end; tmpval = getfield( g, {1}, fieldlist{index, NAME}); % check type % ---------- if ~iscell( fieldlist{index, TYPE} ) res = fieldtest( fieldlist{index, NAME}, fieldlist{index, TYPE}, ... fieldlist{index, VALS}, tmpval, callfunc ); if isstr(res), g = res; return; end; else testres = 0; tmplist = fieldlist; for it = 1:length( fieldlist{index, TYPE} ) res{it} = fieldtest( fieldlist{index, NAME}, fieldlist{index, TYPE}{it}, ... fieldlist{index, VALS}, tmpval, callfunc ); if ~isstr(res{it}), testres = 1; end; end; if testres == 0, g = strvcat(res{:}); return; end; end; end; % check if fields are defined % --------------------------- allfields = fieldnames(g); for index=1:length(allfields) if isempty(strmatch(allfields{index}, fieldlist(:, 1)')) if ~strcmpi(mode, 'ignore') g = [ callfunc 'error: undefined argument ''' allfields{index} '''']; return; end; varargnew{end+1} = allfields{index}; varargnew{end+1} = getfield(g, {1}, allfields{index}); end; end; function g = fieldtest( fieldname, fieldtype, fieldval, tmpval, callfunc ); NAME = 1; TYPE = 2; VALS = 3; DEF = 4; SIZE = 5; g = []; switch fieldtype case { 'integer' 'real' 'boolean' }, if ~isnumeric(tmpval) g = [ callfunc 'error: argument ''' fieldname ''' must be numeric' ]; return; end; if strcmp(fieldtype, 'boolean') if tmpval ~=0 & tmpval ~= 1 g = [ callfunc 'error: argument ''' fieldname ''' must be 0 or 1' ]; return; end; else if strcmp(fieldtype, 'integer') if ~isempty(fieldval) if (isnan(tmpval) & ~any(isnan(fieldval))) ... & (~ismember(tmpval, fieldval)) g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return; end; end; else % real if ~isempty(fieldval) if tmpval < fieldval(1) | tmpval > fieldval(2) g = [ callfunc 'error: value out of range for argument ''' fieldname '''' ]; return; end; end; end; end; case 'string' if ~isstr(tmpval) g = [ callfunc 'error: argument ''' fieldname ''' must be a string' ]; return; end; if ~isempty(fieldval) if isempty(strmatch(lower(tmpval), fieldval)) g = [ callfunc 'error: wrong value for argument''' fieldname '''' ]; return; end; end; case 'cell' if ~iscell(tmpval) g = [ callfunc 'error: argument ''' fieldname ''' must be a cell array' ]; return; end; case 'struct' if ~isstruct(tmpval) g = [ callfunc 'error: argument ''' fieldname ''' must be a structure' ]; return; end; case ''; otherwise, error([ 'finputcheck error: unrecognized type ''' fieldname '''' ]); end;