%FIG2PUBLIC provides an automatic method to export figures, with optional
%uniform styling. Several input/output folders can be given in a single
%call. The routine works both for windows and linux (from Matlab 6.5 to
%7.x).
%
%FIG2PUBLIC is generally used to:
% - make uniform figure styling with batch processing. Styling includes
% font size, marker size, line width, color and figure dimensions
% (for a cleaner figure inclusion). BW color conversion is possible.
% - export figures to eps and optionally pdf, jpeg, png and tiff files.
% By using the eps file as an intermediate file for the other format,
% the typical huge white blank frame around the figures that Matlab
% adds when exporting in other formats is not present.
% - provide a number of pre-defined formats (article, slides, ...)
%
%REQUIREMENTS:
% - formatfig.m : a reduced and developed version of exportfig.m, a
% routine developed by Ben Hinkle (@Mathworks).
% - eps2xxx.m : a figure format converter using ghostscript.
% - presetformat.m : library of format options.
% - addtotex.m : a .tex generator for simpler figure inclusion.
% - ghostscript (minimal version unknown).
%
%CALL:
%
% FIG2PUBLIC( [ OPT_STRUCT, ] [ 'PARAM_NAME', PARAM_VALUE, ] ... )
%
% OPT_STRUCT: structure with fields .PARAM_NAME and values .PARAM_VALUE
%
% NB: for parameters present both in structure and list, the values of
% the list will be used.
%
%PARAMETERS:
%
% inp_folder string or cell array of strings containing the absolute
% input folder paths. Only .fig files contained in these
% folders will be considered. Use the / for linux and the
% \ for windows. Folders starting with '.' are ignored.
% Default: current folder.
%
% dsubset regular expression used to select a subset of
% directories in 'inp_folder'. Useful to use a particular
% set of parameters for a subset of folders having a
% regular name. E.g. 'dsubset' set to 'rect_*' limits
% target folders to those starting with 'rect_'. Default:
% []. Compatibility with 'recursive' is limited.
%
% fsubset regular expression used to select a subset of files in
% 'inp_folder'. Useful to use a particular set of
% parameters for a subset of files having a regular name.
% E.g. 'fsubset' set to 'rect_*' limits target files to
% those starting with 'rect_'. Default: [].
%
% out_folder string or cell array of strings containing the absolute
% output folder paths. Warning: files in these folders
% having the same name as input files will be
% OVERWRITTEN. If a cell array is given for inp_folder, a
% cell array MUST also be given for out_folder. Default:
% current folder. If the given folder does not exist, it
% will be created.
%
% recursive true (default) / false to operate recursively on the
% sub-folders of inp_folder. If there are sub-folders,
% the sub-folder name will be used to target the output
% sub-folder of out_folder.
%
% base_config init a set of parameters with default values. These
% values can then be overwritten by setting parameters
% explicitly. 'base_config' must be set to a string
% combining different default format styles, e.g.:
% 'article' or 'slides'
% 'color', 'bwtl' or 'bw' (see PRESETFORMAT)
% Examples:
% 'articlecolor' exports the figures with the
% default 'article' sizes, using color output.
% Note: optional. Leave empty to use default values of
% FORMATFIG. To get a list of all available default
% format styles, type: <help presetformat>
%
% displayonly true / false (default). If true, the figure is
% displayed and formatting is applied. Then the routine
% is paused and waits for the user to press on "Return".
% No file is saved or exported.
%
% exportonly true / false (default). If true, no figure formatting
% is applied before exportation.
%
% includefig true / false (default). If true, a formatted copy of
% the figure is saved in the output folder as a .fig
% file.
%
% latexcode true (default) / false. If true, a tex file is added to
% the output folder. This file contains latex code
% that can be used to include the figures in the latex
% document. In 'recursive' mode, the sub-folder pattern
% is kept in the figure path to allow direct
% copy-pasting.
% Changed to false if 'displayonly' is true.
% Changed to true if 'latexcodeonly' is true.
%
% latexcodeonly true / false (default). If true, only the .tex files
% will be generated. Nothing else will be done. Useful to
% recreate the correct .tex files if fig2public has been
% called a posteriori on subfolders.
%
% eps_format Matlab driver for the eps output. Default: '-depsc2'.
% Type <help print> to have a complete list of drivers.
% NB: if a non eps driver is given, the eps conversion
% will fail. However, if an empty value is given to
% 'other_formats', this parameter can be used to call
% default Matlab export functions. In that case,
% .print_ext must be defined accordingly.
%
% print_ext Extension of the file returned by the call to print.
% Default: 'eps'. Required because print returns a file
% with a corrupted extension if the filename contains a
% dot. In addition, .eps_format allows any driver, so
% that the file format cannot be guessed.
%
% eps_res resolution of the eps output. Default: 300 dpi.
%
% eps_renderer Renderer used for the eps output. Default: 'painters'.
% If white diagonal stripes appear on pcolor plot,
% 'zbuffer' should be used (Warning: bitmap format). To
% reduce file size, use an appropriate 'width' (see
% FORMATFIG) and a bitmap renderer ('zbuffer').
%
% eps_loose True / False (default). If True, the option '-loose'
% is used in the call to PRINT. This is useful to have
% an exact match between the figure displayed in
% Matlab and the eps file.
%
% gs_path path to the gs executable. Windows users can avoid
% setting this parameter by defining the path in the
% "environment variable" setting. Linux users should not
% have to define it at all.
% For Windows users (at least in XP): go to (in Windows)
% Configuration pannel -> System -> Advanced ->
% Environment Variable -> System Variables -> "Path"
% Then click on "Modify" and add the path to the
% gs executable in the path list.
%
% orientation see EPS2XXX.m. Default: 0.
%
% other_formats cell array of export format. Possible values are:
% 'pdf', 'jpeg', 'png' and 'tiff'. Default: {'pdf'}
%
% other_resolution
% resolution of the other format output. Default: 300
% dpi.
%
% dointerp see EPS2XXX.m. Default: true.
%
% ANY OTHER FORMATFIG parameter-value pair (use: <help formatfig> to get
% a list) is allowed as input of FIG2PUBLIC.
%
%
%STANDARD CALLS:
%
% For standard publications:
%
% fig2public('inp_folder',{'my_inp_path1','my_inp_path2',...}, ...
% 'out_folder',{'my_out_path1','my_out_path2',...}, ...
% 'base_config','article small bwtl tightx aligned')
%
% For reports, change 'base_config' to:
% ..., 'base_config', 'article large bwtl tightx aligned', ...
%
% For slides:
% ..., 'base_config', 'slides large color tightx aligned', ...
%
%SPECIAL CALL EXAMPLES
%
% Give custom values to some FORMATFIG options (NB: last options in the
% list superseed previous ones):
%
% fig2public( ..., 'linemode', 'fixed', 'linewidth', 2, ...
% 'lockticks', true, 'tight', 'x', ... );
%
% The options above means that all lines will have a width of 2, that
% the axes ticks will be locked (useful for log axis in general) and
% that the figure margins will be minimized while keeping the figure
% width untouched and the height to scale. Note that some parameters
% are given as strings, others as boolean and others as scalars.
%
% Advanced usage: absolute control of exported figure width:
%
% fig2public( ..., 'width', 10, 'eps_loose', true, 'tight', 'x', ...
% 'activeposition', 'position' );
%
% Strictly speaking, only 'width' and 'eps_loose' are necessary for
% absolute control of exported figure width. 'tight' minimizes the
% margins and 'activeposition' is used to get a better margin
% control.
%
%
% Last modification: Jonathan Rossel, 15.12.2010
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Modif log: (see file)
% 22.07.08 J.Rossel Added: create output folder if
% inexistant.
% Added: 'recursive' option.
%
% 29.07.08 J.Rossel Set 'article' configuration:
% -fontsize: 10 (prev. 12)
% -markersize: 6 (prev. 8)
% -linewidth: 0.5 (prev. 1)
% Added 'dointerp' option
%
% 29.10.08 J.Rossel Added: 'latexcode' option.
%
% 20.04.09 J.Rossel Modif:
% - No outpuf folder required if
% 'displayonly' is true
% - Error if 'includefig' is true
% and same input/output folders.
% - 'latexcode' is false if
% 'displayonly' is true
% Added: 'latexcodeonly' option
%
% 10.06.09 J.Rossel - 'bw' option of 'base_config'
% modified
% - Recursive option modified to avoid
% infinite loop if the output folder
% is a child of the input folder
%
% 16.06.09 J.Rossel eps_renderer option added
%
% 24.06.09 J.Rossel - 'fsubset' option added.
% - structure input allowed.
%
% 18.12.09 J.Rossel 'print_ext' option added to allow
% correct treatment of files with
% dots in their name.
%
% 11.01.10 J.Rossel allow call without parameters.
%
% 16.06.10 J.Rossel 'dsubset' option added, 'fsubset'
% limited to files.
%
% 16.08.10 J.Rossel input formatting for formatfig
% modified (intern).
%
% 12.10.10 J.Rossel 'eps_loose' added
%
% 25.11.10 J.Rossel Code cleaning and test input param
% name.
%
% 15.12.10 J.Rossel Default format styles externalized
% in PRESETFORMAT.m
function fig2public(varargin);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Misc inits
%version
verstr = version;
majorver = str2num(verstr(1));
%determine the kind of slash that is used
kindslash = filesep;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Expand first argument if structure. Store varargin.
%check if first arg is a structure. Expand it if nec.
if nargin > 0,
if isstruct( varargin{1} ),
param_values = struct2cell( varargin{1} );
param_names = fieldnames( varargin{1} );
param = cell( 1, 2*length( param_names ) );
param(1:2:end-1) = param_names;
param(2:2:end) = param_values;
varargin(1) = []; %remove the structure
varargin = { param{:}, varargin{:} }; %add the structure as a list (start the param list with it to keep parameter hierarchy)
end
else
varargin = {};
end
%save varargin (for recursive calls)
oldvarargin = varargin;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Set default parameters for local and export uses
%set default paths and local options
localopt = struct( ...
'inp_folder', {{pwd}}, ...
'out_folder', {{pwd}}, ...
'dsubset', [], ...
'fsubset', [], ...
'exportonly', false, ...
'includefig', false, ...
'displayonly', false, ...
'recursive', true, ...
'latexcode', true, ... %false if displayonly=true, see below
'latexcodeonly', false, ...
'latexfigroot', []); %latexfigroot is an internal option only. It is used in recursive mode.
fieldnameslocal = fieldnames(localopt);
%use default configurations as a base for input parameters
%for formatfig and exporting
formatfigopt = formatfig; %empty call to get default structure
fieldnamesformat = fieldnames( formatfigopt );
expfigopt = struct(...
'eps_format', '-depsc2', ...
'eps_res', 300, ...
'eps_renderer', 'painters', ...
'print_ext', 'eps', ...
'eps_loose', false, ...
'gspath', [], ...
'orientation', 0, ...
'other_formats', {{'pdf'}}, ...
'other_resolution', 300, ...
'dointerp', true );
fieldnamesexp = fieldnames(expfigopt);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Check that given input parameters are allowed.
%Group all the allowed parameters in a single cell array
allowedpar = [ fieldnameslocal; fieldnamesformat; fieldnamesexp; { 'base_config' } ];
inppar = varargin( 1 : 2 : end ); %cell array with input parameter names
%loop on input parameter names and check their value
for ii = 1 : length( inppar )
if ~any( strcmpi( allowedpar, inppar{ ii } ) )
error( [ 'FIG2PUBLIC: ''', inppar{ ii }, ''' is not an allowed parameter.' ] );
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Apply base configurations
indbc = find( strcmpi( varargin, 'base_config' ) );
if ~isempty( indbc ),
bc = varargin{ indbc( end ) + 1 }; %use 'end' in case the parameter has been given multiple times
[ formatfigopt, expfigopt ] = presetformat( formatfigopt, expfigopt, bc );
%remove the base configuration parameter
varargin( indbc( end ) : indbc( end ) + 1 ) = [];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Replace defaults by user-defined values
%fill the local and export structures with the input
%NB: for formatfig, the loop is done in formatfig itself.
ind = [];
for j=1:2:length(varargin)-1 %for figure exportation
if any(strcmpi(fieldnamesexp,varargin{j})),
expfigopt = subsasgn(expfigopt,struct('type','.','subs',lower(varargin{j})),varargin{j+1});
%keep a track of the parameters set in the structure
ind = [ind,j,j+1];
end
end
for j=1:2:length(varargin)-1 %for local
if any(strcmpi(fieldnameslocal,varargin{j})),
localopt = subsasgn(localopt,struct('type','.','subs',lower(varargin{j})),varargin{j+1});
%keep a track of the parameters set in the structure
ind = [ind,j,j+1];
end
end
%remove the unnecessary parameters from the varargin list
varargin(ind) = [];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Check some inputs: target folders, generation of latex code
%init variables
inp_folder = localopt.inp_folder;
out_folder = localopt.out_folder;
latexfigroot = localopt.latexfigroot;
%check out_folder
if localopt.includefig & any( strcmp( inp_folder, out_folder ) ),
error( 'If includefig==true, the output folder must be different from the input folder');
end
%check: only's. Max 1 at a time.
tmp = [ localopt.displayonly, localopt.exportonly, localopt.latexcodeonly ];
if length( find( tmp ) ) > 1,
error( 'Max 1 "only" option can be set to true at a time' );
end
%avoid latex code generation when displayonly
if localopt.displayonly,
localopt.latexcode = false;
end
%force latexcode if latexcodeonly
if localopt.latexcodeonly,
localopt.latexcode = true;
end
%clean input format
if ischar(inp_folder),
inp_folder = {inp_folder};
end
if ischar(out_folder),
out_folder = {out_folder};
end
if isempty(latexfigroot),
latexfigroot = out_folder;
elseif ischar(latexfigroot),
latexfigroot = {latexfigroot};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Loop on target folders
for jj = 1:length(inp_folder),
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Check folder input format and existence. Prepare latex file if nec.
%clean input format
if ~strcmp(inp_folder{jj}(end),kindslash),
inp_folder{jj} = [inp_folder{jj},kindslash];
end
if ~strcmp(out_folder{jj}(end),kindslash),
out_folder{jj} = [out_folder{jj},kindslash];
end
if ~strcmp(latexfigroot{jj}(end),kindslash),
latexfigroot{jj} = [latexfigroot{jj},kindslash];
end
%check existence of folders
if exist(inp_folder{jj},'dir') ~= 7, error(['The input folder ',inp_folder{jj},' has not been found.']); end
if ~localopt.displayonly,
if exist(out_folder{jj},'dir') ~= 7,
%create the folder
eval(['!mkdir ', out_folder{jj}]);
end
end
if localopt.latexcode,
%a file containing code allowing figure inclusion in Latex will be
%added in each output folder
texfile = [out_folder{jj},'texinclcode.tex'];
fidtex = fopen(texfile,'w'); %create or overwrite
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Loop on fig files
%get filenames (filenames only) in current directory
filenames = dir( [ inp_folder{jj}, localopt.fsubset ] ); %limit to fsubset
fileisdir = [filenames(:).isdir]; %the file is actually a folder
filenames = {filenames( ~fileisdir ).name};
%process files in current directory
for ii = 1:length(filenames),
%check the file
thisfile = filenames{ii};
if strcmp( thisfile( 1 ), '.' ),
%file starting with . are ignored
continue
end
ext = thisfile(end-2:end);
if ~strcmp(ext,'fig'),
%the file is a file but not a fig file
continue
end
%remove the extension
thisfile(end-3:end) = [];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Figure formatting
if ~localopt.latexcodeonly,
%open the figure
openfig([inp_folder{jj},thisfile,'.fig']);
if ~localopt.exportonly,
%format
formatfig(gcf,formatfigopt,varargin{:});
end
if localopt.displayonly,
pause
close
continue
end
if localopt.includefig,
%save a formatted fig file in the output folder
saveas(gcf,[out_folder{jj},thisfile],'fig');
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Latex code generation
%add the code to the tex file
if localopt.latexcode,
tmp = [out_folder{jj},thisfile]; %complete file name, without extension
tmp = strrep(tmp,latexfigroot{jj},''); %remove the latexfigroot from the file name
tmp = strrep(tmp,'\','/'); %latex slash format
addtotex(fidtex,tmp,thisfile);
if localopt.latexcodeonly,
continue
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Figure exportation
%export to eps (or other format defined in fields .eps_format and .print_ext)
printoptions = { expfigopt.eps_format, ...
['-',expfigopt.eps_renderer], ...
['-r',num2str(expfigopt.eps_res)], ...
[out_folder{jj},thisfile,'.',expfigopt.print_ext] };
if expfigopt.eps_loose
printoptions = { printoptions{ 1 : 3 }, '-loose', printoptions{ 4 : end } };
end
print( printoptions{:} ); %call print
%convert to other formats
if ~isempty(expfigopt.other_formats) & strcmpi( expfigopt.print_ext, 'eps' ),
eps2xxx([out_folder{jj},thisfile,'.eps'],expfigopt.other_formats, ...
expfigopt.gspath,expfigopt.orientation,expfigopt.other_resolution,expfigopt.dointerp);
end
close
end %end loop on files
if localopt.latexcode,
%close the file
fclose(fidtex);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Recursive mode
if localopt.recursive,
%process directories in current directory
%get dirnames (directories only)
dirnames = dir( [ inp_folder{jj}, localopt.dsubset ] ); %limit to dsubset
fileisdir = [dirnames(:).isdir]; %the file is actually a folder
dirnames = {dirnames( fileisdir ).name};
for ii = 1:length(dirnames),
%check the directory
thisdir = dirnames{ii};
if strcmp( thisdir( 1 ), '.' ),
%. .. or folders starting with . are ignored
continue
end
%call fig2public recursively
newvarargin = oldvarargin; %don't modify the old one
newinp = [inp_folder{jj},thisdir]; %complete path to input subfolder
newout = [out_folder{jj},thisdir]; %complete path to output subfolder. Will be created if necessary
%check that the new input is not the current output folder
%in which case an infinite loop would happen. If it is,
%skip it
if strcmp( [ newinp, kindslash ], out_folder{ jj } ),
continue
end
tmp = find(strcmpi(newvarargin,'inp_folder'));
if isempty( tmp ),
%default path was used, add the option at the end of
%the list
newvarargin( end+1 : end+2 ) = { 'inp_folder', newinp };
else
newvarargin{tmp+1} = newinp; %update folders
end
tmp = find(strcmpi(newvarargin,'out_folder'));
if isempty( tmp ),
%default path was used, add the option at the end of
%the list
newvarargin( end+1 : end+2 ) = { 'out_folder', newout };
else
newvarargin{tmp+1} = newout; %update folders
end
tmp = find(strcmpi(oldvarargin,'latexfigroot'));
if isempty(tmp),
%this is the external call of fig2public
%set latexfigroot to keep the sub-folders in the fig
%paths
newvarargin(end+1:end+2) = {'latexfigroot',out_folder{jj}};
end
%call fig2public with all the same parameters, apart from
%input/output folders
fig2public(newvarargin{:});
end %end loop on subdir
end %end recursive mode
end %end loop on target folders