GENERATEFIGURES Generate figures from glider data. Syntax: FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST) FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPTIONS) FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPT1, VAL1, ...) Description: FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST) generate figures specified in struct FIGURE_LIST from glider data in struct DATA, and returns information about generated image files in struct FIGURE_INFO. FIGURE_LIST is a struct where each field specifies a figure to generate. Field names are figure keys identifying each particular figure, and field values are structs with the following fields: PLOTFUNC: plotting function. String or function handle specifying which function should be used to generate the figure plot. DATAOPTS: data options. Struct array with the mapping between data plot options (field names) and variables in struct DATA (field values). Each field value may be either a string or a string cell array with a list of variable name choices in order of preference. The first variable present in DATA containing some valid value will be added to the plot options given in option PLOTOPTS, using the same field name given in DATAOPTS. PLOTOPTS: plot style options. Struct array with extra plot options to pass to plotting function given in PLOTFUNC. It can also serve to specify default data option values. These values will be used when none of the choices specified in DATAOPTSis present in DATA. PRNTOPTS: print options. Struct array with print options to pass to function PRINTFIGURE. FIGURE_INFO is a struct containing information about the generated figures. Fields are named after corresponding figure keys, and their value is the output of the call to PRINTFIGURE. Only figures whose data is available in struct DATA are generated, other figures are silently omitted. FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPT1, VAL1, ...) and FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPTIONS) allows passing the following options of PRINTFIGURE in key-value pairs OPT1, VAL1... or in a struct OPTIONS with field names as option names and field values as option values: DIRNAME: image file directory. Default value: '' (empty, use current directory) FORMAT: image file format (extension) Default value: 'eps' RESOLUTION: image resolution in dots per inch. Default value: 72 DRIVER: driver to print intermediate vector image file. Default value: 'epsc2' RENDER: renderer to use when printing intermediate vector file. Default value: [] (renderer automatically selected) LOOSE: uncrop image when printing intermediate vector file. Default value: 'loose' (produce uncropped images). CONVERT: program to convert intermediate vector file to final format. Default value: 'convert' KEEPEPS: preserve intermediate vector file after conversion. Default value: false DATE: image generation timestamp. Default value: datestr(now(), 31) Examples: % Assuming data is a processed glider data structure, % plot CTD trajectory data: % Plot a transect vertical section of temperature. figure_list.temperature = struct(); figure_list.temperature.plotfunc = @plotTransectVerticalSection; % Using covered planar distance as horizontal coordinate, and using % depth from CTD pressure if available, otherwise use navigation depth. figure_list.temperature.dataopts.xdata = 'distance_over_ground'; figure_list.temperature.dataopts.ydata = {'depth_ctd' 'depth'}; figure_list.temperature.dataopts.cdata = 'temperature'; % Add labels, title and some extra options. figure_list.temperature.plotopts.sdata = 4; figure_list.temperature.plotopts.xlabel = struct('String', 'distance (km)'); figure_list.temperature.plotopts.ylabel = struct('String', 'depth (m)'); figure_list.temperature.plotopts.clabel = struct('String', 'temperature (deg C)'); figure_list.temperature.plotopts.title = struct('String', 'In situ temperature'); figure_list.temperature.plotopts.axsprops = struct('Ydir', 'reverse'); % Set printing options. figure_list.temperature.prntopts = struct('filename', 'ctd_temp', ... 'title', 'Temperature section', ... 'comment', 'Cross section of in situ measured temperature.'); % Make similar figures for salinity and density: figure_list.salinity = struct(); figure_list.salinity.plotfunc = @plotTransectVerticalSection; figure_list.salinity.dataopts.xdata = 'distance_over_ground'; figure_list.salinity.dataopts.ydata = {'depth_ctd' 'depth'}; figure_list.salinity.dataopts.cdata = 'salinity'; figure_list.salinity.plotopts.sdata = 4; figure_list.salinity.plotopts.xlabel = struct('String', 'distance (km)'); figure_list.salinity.plotopts.ylabel = struct('String', 'depth (m)'); figure_list.salinity.plotopts.clabel = struct('String', 'salinity (PSU)'); figure_list.salinity.plotopts.title = struct('String', 'In situ salinity'); figure_list.salinity.plotopts.axsprops = struct('Ydir', 'reverse'); figure_list.salinity.prntopts = struct('filename', 'ctd_salt', ... 'title', 'Temperature section', ... 'comment', 'Cross section of in situ derived salinity.'); figure_list.density = struct(); figure_list.density.plotfunc = @plotTransectVerticalSection; figure_list.density.dataopts.xdata = 'distance_over_ground'; figure_list.density.dataopts.ydata = {'depth_ctd' 'depth'}; figure_list.density.dataopts.cdata = 'density'; figure_list.density.plotopts.sdata = 4; figure_list.density.plotopts.xlabel = struct('String', 'distance (km)'); figure_list.density.plotopts.ylabel = struct('String', 'depth (m)'); figure_list.density.plotopts.clabel = struct('String', 'density (PSU)'); figure_list.density.plotopts.title = struct('String', 'In situ density'); figure_list.density.plotopts.axsprops = struct('Ydir', 'reverse'); figure_list.density.prntopts = struct('filename', 'ctd_dens', ... 'title', 'Temperature section', ... 'comment', 'Cross section of in situ derived density.'); % Plot them at once to current directory, using default format. figure_info = generateGliderFigures(data, figure_list) % Plot them to desired image directory, selecting format and resolution. figure_info = generateGliderFigures(data, figure_list, ... 'dirname', 'figures', ... 'format', 'png', ... 'resolution', 150) See also: PRINTFIGURE PLOTTRANSECTVERTICALSECTION PLOTTSDIAGRAM PLOTPROFILESTATISTICS CONFIGFIGURES DATESTR NOW Authors: Joan Pau Beltran <joanpau.beltran@socib.cat>
0001 function figure_info = generateGliderFigures(data, figure_list, varargin) 0002 %GENERATEFIGURES Generate figures from glider data. 0003 % 0004 % Syntax: 0005 % FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST) 0006 % FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPTIONS) 0007 % FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPT1, VAL1, ...) 0008 % 0009 % Description: 0010 % FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST) generate figures 0011 % specified in struct FIGURE_LIST from glider data in struct DATA, and 0012 % returns information about generated image files in struct FIGURE_INFO. 0013 % FIGURE_LIST is a struct where each field specifies a figure to generate. 0014 % Field names are figure keys identifying each particular figure, and field 0015 % values are structs with the following fields: 0016 % PLOTFUNC: plotting function. 0017 % String or function handle specifying which function should be used to 0018 % generate the figure plot. 0019 % DATAOPTS: data options. 0020 % Struct array with the mapping between data plot options (field names) 0021 % and variables in struct DATA (field values). Each field value may be 0022 % either a string or a string cell array with a list of variable name 0023 % choices in order of preference. The first variable present in DATA 0024 % containing some valid value will be added to the plot options given in 0025 % option PLOTOPTS, using the same field name given in DATAOPTS. 0026 % PLOTOPTS: plot style options. 0027 % Struct array with extra plot options to pass to plotting function given 0028 % in PLOTFUNC. It can also serve to specify default data option values. 0029 % These values will be used when none of the choices specified in 0030 % DATAOPTSis present in DATA. 0031 % PRNTOPTS: print options. 0032 % Struct array with print options to pass to function PRINTFIGURE. 0033 % FIGURE_INFO is a struct containing information about the generated figures. 0034 % Fields are named after corresponding figure keys, and their value is the 0035 % output of the call to PRINTFIGURE. Only figures whose data is available in 0036 % struct DATA are generated, other figures are silently omitted. 0037 % 0038 % FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPT1, VAL1, ...) and 0039 % FIGURE_INFO = GENERATEGLIDERFIGURES(DATA, FIGURE_LIST, OPTIONS) allows 0040 % passing the following options of PRINTFIGURE in key-value pairs OPT1, 0041 % VAL1... or in a struct OPTIONS with field names as option names and 0042 % field values as option values: 0043 % DIRNAME: image file directory. 0044 % Default value: '' (empty, use current directory) 0045 % FORMAT: image file format (extension) 0046 % Default value: 'eps' 0047 % RESOLUTION: image resolution in dots per inch. 0048 % Default value: 72 0049 % DRIVER: driver to print intermediate vector image file. 0050 % Default value: 'epsc2' 0051 % RENDER: renderer to use when printing intermediate vector file. 0052 % Default value: [] (renderer automatically selected) 0053 % LOOSE: uncrop image when printing intermediate vector file. 0054 % Default value: 'loose' (produce uncropped images). 0055 % CONVERT: program to convert intermediate vector file to final format. 0056 % Default value: 'convert' 0057 % KEEPEPS: preserve intermediate vector file after conversion. 0058 % Default value: false 0059 % DATE: image generation timestamp. 0060 % Default value: datestr(now(), 31) 0061 % 0062 % Examples: 0063 % % Assuming data is a processed glider data structure, 0064 % % plot CTD trajectory data: 0065 % % Plot a transect vertical section of temperature. 0066 % figure_list.temperature = struct(); 0067 % figure_list.temperature.plotfunc = @plotTransectVerticalSection; 0068 % % Using covered planar distance as horizontal coordinate, and using 0069 % % depth from CTD pressure if available, otherwise use navigation depth. 0070 % figure_list.temperature.dataopts.xdata = 'distance_over_ground'; 0071 % figure_list.temperature.dataopts.ydata = {'depth_ctd' 'depth'}; 0072 % figure_list.temperature.dataopts.cdata = 'temperature'; 0073 % % Add labels, title and some extra options. 0074 % figure_list.temperature.plotopts.sdata = 4; 0075 % figure_list.temperature.plotopts.xlabel = struct('String', 'distance (km)'); 0076 % figure_list.temperature.plotopts.ylabel = struct('String', 'depth (m)'); 0077 % figure_list.temperature.plotopts.clabel = struct('String', 'temperature (deg C)'); 0078 % figure_list.temperature.plotopts.title = struct('String', 'In situ temperature'); 0079 % figure_list.temperature.plotopts.axsprops = struct('Ydir', 'reverse'); 0080 % % Set printing options. 0081 % figure_list.temperature.prntopts = struct('filename', 'ctd_temp', ... 0082 % 'title', 'Temperature section', ... 0083 % 'comment', 'Cross section of in situ measured temperature.'); 0084 % % Make similar figures for salinity and density: 0085 % figure_list.salinity = struct(); 0086 % figure_list.salinity.plotfunc = @plotTransectVerticalSection; 0087 % figure_list.salinity.dataopts.xdata = 'distance_over_ground'; 0088 % figure_list.salinity.dataopts.ydata = {'depth_ctd' 'depth'}; 0089 % figure_list.salinity.dataopts.cdata = 'salinity'; 0090 % figure_list.salinity.plotopts.sdata = 4; 0091 % figure_list.salinity.plotopts.xlabel = struct('String', 'distance (km)'); 0092 % figure_list.salinity.plotopts.ylabel = struct('String', 'depth (m)'); 0093 % figure_list.salinity.plotopts.clabel = struct('String', 'salinity (PSU)'); 0094 % figure_list.salinity.plotopts.title = struct('String', 'In situ salinity'); 0095 % figure_list.salinity.plotopts.axsprops = struct('Ydir', 'reverse'); 0096 % figure_list.salinity.prntopts = struct('filename', 'ctd_salt', ... 0097 % 'title', 'Temperature section', ... 0098 % 'comment', 'Cross section of in situ derived salinity.'); 0099 % figure_list.density = struct(); 0100 % figure_list.density.plotfunc = @plotTransectVerticalSection; 0101 % figure_list.density.dataopts.xdata = 'distance_over_ground'; 0102 % figure_list.density.dataopts.ydata = {'depth_ctd' 'depth'}; 0103 % figure_list.density.dataopts.cdata = 'density'; 0104 % figure_list.density.plotopts.sdata = 4; 0105 % figure_list.density.plotopts.xlabel = struct('String', 'distance (km)'); 0106 % figure_list.density.plotopts.ylabel = struct('String', 'depth (m)'); 0107 % figure_list.density.plotopts.clabel = struct('String', 'density (PSU)'); 0108 % figure_list.density.plotopts.title = struct('String', 'In situ density'); 0109 % figure_list.density.plotopts.axsprops = struct('Ydir', 'reverse'); 0110 % figure_list.density.prntopts = struct('filename', 'ctd_dens', ... 0111 % 'title', 'Temperature section', ... 0112 % 'comment', 'Cross section of in situ derived density.'); 0113 % % Plot them at once to current directory, using default format. 0114 % figure_info = generateGliderFigures(data, figure_list) 0115 % % Plot them to desired image directory, selecting format and resolution. 0116 % figure_info = generateGliderFigures(data, figure_list, ... 0117 % 'dirname', 'figures', ... 0118 % 'format', 'png', ... 0119 % 'resolution', 150) 0120 % 0121 % See also: 0122 % PRINTFIGURE 0123 % PLOTTRANSECTVERTICALSECTION 0124 % PLOTTSDIAGRAM 0125 % PLOTPROFILESTATISTICS 0126 % CONFIGFIGURES 0127 % DATESTR 0128 % NOW 0129 % 0130 % Authors: 0131 % Joan Pau Beltran <joanpau.beltran@socib.cat> 0132 0133 % Copyright (C) 2013-2016 0134 % ICTS SOCIB - Servei d'observacio i prediccio costaner de les Illes Balears 0135 % <http://www.socib.es> 0136 % 0137 % This program is free software: you can redistribute it and/or modify 0138 % it under the terms of the GNU General Public License as published by 0139 % the Free Software Foundation, either version 3 of the License, or 0140 % (at your option) any later version. 0141 % 0142 % This program is distributed in the hope that it will be useful, 0143 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0144 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0145 % GNU General Public License for more details. 0146 % 0147 % You should have received a copy of the GNU General Public License 0148 % along with this program. If not, see <http://www.gnu.org/licenses/>. 0149 0150 error(nargchk(2, 20, nargin, 'struct')); 0151 0152 0153 %% Set plot options and default values. 0154 options.dirname = ''; 0155 options.format = 'eps'; 0156 options.resolution = 72; 0157 options.driver = 'epsc2'; 0158 options.render = []; 0159 options.loose = 'loose'; 0160 options.convert = 'convert'; 0161 options.keepeps = false; 0162 options.date = datestr(now(), 31); 0163 0164 0165 %% Get options from extra arguments. 0166 % Parse option key-value pairs in any accepted call signature. 0167 if isscalar(varargin) && isstruct(varargin{1}) 0168 % Options passed as a single option struct argument: 0169 % field names are option keys and field values are option values. 0170 option_key_list = fieldnames(varargin{1}); 0171 option_val_list = struct2cell(varargin{1}); 0172 elseif mod(numel(varargin), 2) == 0 0173 % Options passed as key-value argument pairs. 0174 option_key_list = varargin(1:2:end); 0175 option_val_list = varargin(2:2:end); 0176 else 0177 error('glider_toolbox:generateFigures:InvalidOptions', ... 0178 'Invalid optional arguments (neither key-value pairs nor struct).'); 0179 end 0180 % Overwrite default options with values given in extra arguments. 0181 for opt_idx = 1:numel(option_key_list) 0182 opt = lower(option_key_list{opt_idx}); 0183 val = option_val_list{opt_idx}; 0184 if isfield(options, opt) 0185 options.(opt) = val; 0186 else 0187 error('glider_toolbox:generateFigures:InvalidOption', ... 0188 'Invalid option: %s.', opt); 0189 end 0190 end 0191 0192 0193 %% Initialize output. 0194 figure_info = struct(); 0195 0196 0197 %% Generate figures given in figure list, if data is available. 0198 figure_key_list = fieldnames(figure_list); 0199 for figure_key_idx = 1:numel(figure_key_list); 0200 % Get current figure key and settings. 0201 figure_key = figure_key_list{figure_key_idx}; 0202 figure_plot = figure_list.(figure_key); 0203 % Set print options (figure options override global options). 0204 if isfield(figure_plot, 'prntopts') 0205 print_options = figure_plot.prntopts; 0206 else 0207 print_options = struct(); 0208 end 0209 print_option_field_list = fieldnames(options); 0210 for print_option_field_idx = 1:numel(print_option_field_list) 0211 print_option_field = print_option_field_list{print_option_field_idx}; 0212 if ~isfield(print_options, print_option_field) 0213 print_options.(print_option_field) = options.(print_option_field); 0214 end 0215 end 0216 % Get plot function as function handle. 0217 plot_function = figure_plot.plotfunc; 0218 if ischar(figure_plot.plotfunc) 0219 plot_function = str2func(figure_plot.plotfunc); 0220 end 0221 % Get plot extra options. 0222 if isfield(figure_plot, 'plotopts') 0223 plot_options = figure_plot.plotopts; 0224 else 0225 plot_options = struct(); 0226 end 0227 % Get plot data options. 0228 data_option_field_list = fieldnames(figure_plot.dataopts); 0229 data_options = repmat(struct(), size(figure_plot.dataopts)); 0230 for data_option_idx = 1:numel(figure_plot.dataopts) 0231 dataopt = figure_plot.dataopts(data_option_idx); 0232 for data_option_field_idx = 1:numel(data_option_field_list) 0233 data_option_field = data_option_field_list{data_option_field_idx}; 0234 data_options(data_option_idx).(data_option_field) = ''; 0235 if ischar(dataopt.(data_option_field)) 0236 data_option_value_list = {dataopt.(data_option_field)}; 0237 else 0238 data_option_value_list = dataopt.(data_option_field); 0239 end 0240 for data_option_value_idx = 1:numel(data_option_value_list) 0241 data_option_value = data_option_value_list{data_option_value_idx}; 0242 if isfield(data, data_option_value) ... 0243 && ~all(isnan(data.(data_option_value)(:))) 0244 data_options(data_option_idx).(data_option_field) = data_option_value; 0245 break 0246 end 0247 end 0248 end 0249 end 0250 % Generate figure if all data is there. 0251 % Data specified in dataopts should be in data options, 0252 % data_available = all(isfield(data_options, data_option_field_list)) ... 0253 % && ~any(any(cellfun(@isempty, struct2cell(data_options)))); 0254 data_option_field_missing = ... 0255 any(cellfun(@isempty, struct2cell(data_options(:))), 2); 0256 data_available = ... 0257 ~any(data_option_field_missing) || ... 0258 all(isfield(plot_options, data_option_field_list(data_option_field_missing))); 0259 if data_available 0260 fprintf('Generating figure %s with settings:\n', figure_key); 0261 fprintf(' plot function : %s\n', func2str(plot_function)); 0262 for data_option_field_idx = 1:numel(data_option_field_list) 0263 data_option_field = data_option_field_list{data_option_field_idx}; 0264 data_option_value_str = cell(size(data_options)); 0265 if isscalar(data_options) 0266 data_option_value = data_options.(data_option_field); 0267 if isempty(data_option_value) 0268 data_option_value_str{1} = ... 0269 sprintf('[%dx%d %s]', ... 0270 size(plot_options.(data_option_field)), ... 0271 class(plot_options.(data_option_field))); 0272 else 0273 data_option_value_str{1} = data_option_value; 0274 plot_options.(data_option_field) = data.(data_option_value); 0275 end 0276 else 0277 for data_option_idx = 1:numel(data_options) 0278 data_option_value = data_options(data_option_idx).(data_option_field); 0279 if isempty(data_option_value) 0280 data_option_value_str{data_option_idx} = ... 0281 sprintf('[%dx%d %s]', ... 0282 size(plot_options.(data_option_field){data_option_idx}), ... 0283 class(plot_options.(data_option_field){data_option_idx})); 0284 else 0285 data_option_value_str{data_option_idx} = data_option_value; 0286 plot_options.(data_option_field){data_option_idx} = ... 0287 data.(data_option_value); 0288 end 0289 end 0290 end 0291 fprintf(' %-16s :%s\n', ... 0292 data_option_field, sprintf(' %-16s', data_option_value_str{:})); 0293 end 0294 figure_handle = figure(); 0295 try 0296 plot_function(figure_handle, plot_options); 0297 figure_info.(figure_key) = printfigure(figure_handle, print_options); 0298 catch exception 0299 fprintf('Figure generation failed:\n'); 0300 disp(getReport(exception, 'extended')); 0301 end 0302 close(figure_handle); 0303 end 0304 0305 end 0306 0307 end