Skip to content

Commit 89a27c9

Browse files
committed
First version of map plotting routines
1 parent a255d77 commit 89a27c9

File tree

2 files changed

+378
-0
lines changed

2 files changed

+378
-0
lines changed

auxil/plot_maps.m

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
function plot_maps(Data, Mdata, variables, depths, sz, basename, varargin)
2+
% plot_maps This function is part of the
3+
% MATLAB toolbox for accessing Argo float data.
4+
%
5+
% USAGE:
6+
% plot_maps(Data, Mdata, variables, basename, varargin)
7+
%
8+
% DESCRIPTION:
9+
% This function plots maps of values for the specified variable(s)
10+
% and float(s) at the given depth(s).
11+
%
12+
% PREREQUISITE:
13+
% (S)prof file(s) for the specified float(s) must exist locally.
14+
%
15+
% INPUTS:
16+
% Data : struct that must contain the PRES field and the given
17+
% variables (_ADJUSTED fields are used if available)
18+
% Mdata : struct that must contain the WMO_ID field
19+
% variables : cell array with names of the measured fields (e.g., {'DOXY'})
20+
% depths : array of the depths to be plotted
21+
% sz : sz defines the size of plotted points
22+
% basename : if not empty, create png files of all plots;
23+
% the file names will be <variable>_<depth>dbar.png
24+
%
25+
% OPTIONAL INPUTS:
26+
% 'caxis',[cmin cmax] : specify the minimum and maximum value to be
27+
% shown (for all variables and depths)
28+
% default: automatic scaling for each variable and depth
29+
% separately
30+
% 'qc',flags : show only values with the given QC flags (array)
31+
% 0: no QC was performed;
32+
% 1: good data;
33+
% 2: probably good data;
34+
% 3: probably bad data that are potentially correctable;
35+
% 4: bad data;
36+
% 5: value changed;
37+
% 6,7: not used;
38+
% 8: estimated value;
39+
% 9: missing value
40+
% default setting: 0:9 (all flags)
41+
% See Table 7 in Bittig et al.:
42+
% https://www.frontiersin.org/files/Articles/460352/fmars-06-00502-HTML-r1/image_m/fmars-06-00502-t007.jpg
43+
% 'raw',raw : plot raw, i.e., unadjusted data if set to 'yes';
44+
% default: 'no' (i.e., plot adjusted data if
45+
% available)
46+
% 'no_strict': plot only adjusted data, skip floats
47+
% that have only raw data available
48+
%
49+
% OUTPUT: None.
50+
%
51+
% AUTHORS:
52+
% H. Frenzel, J. Sharp, A. Fassbender (NOAA-PMEL), N. Buzby (UW)
53+
%
54+
% CITATION:
55+
% H. Frenzel, J. Sharp, A. Fassbender, N. Buzby, 2022. OneArgo-Mat:
56+
% A MATLAB toolbox for accessing and visualizing Argo data.
57+
% Zenodo. https://doi.org/10.5281/zenodo.6588041
58+
%
59+
% LICENSE: oneargo_mat_license.m
60+
%
61+
% DATE: JUNE 1, 2022 (Version 1.0.1)
62+
63+
global Settings;
64+
65+
66+
if nargin < 5
67+
warning(['Usage: plot_maps(Data, Mdata, variables, depth, basename, ', ...
68+
'[, varargin])'])
69+
return;
70+
end
71+
72+
% set defaults
73+
cax = [];
74+
depth = [];
75+
raw = 'no'; % plot adjusted data by default
76+
qc_flags = 0:9; % use all data
77+
title_add = '';
78+
79+
% parse optional arguments
80+
for f = 1:2:length(varargin)-1
81+
if strcmpi(varargin{f}, 'caxis')
82+
cax = varargin{f+1};
83+
elseif strcmpi(varargin{f}, 'raw')
84+
raw = varargin{f+1};
85+
elseif strcmpi(varargin{f}, 'qc')
86+
qc_flags = varargin{f+1};
87+
else
88+
warning('unknown option: %s', varargin{f});
89+
end
90+
end
91+
92+
floats = fieldnames(Data);
93+
nfloats = length(floats);
94+
if ~nfloats
95+
warning('no floats found in Data structure')
96+
return
97+
end
98+
99+
float_ids = fieldnames(Mdata);
100+
nvars = length(variables);
101+
ndepths = length(depths);
102+
nplots = ndepths * nvars;
103+
104+
if nplots > Settings.max_plots
105+
warning(['too many plots requested - use fewer depths and/or variables', ...
106+
newline, 'or increase Settings.max_plots if possible'], ...
107+
warn_insert)
108+
return
109+
end
110+
111+
% unless 'raw' is specified, plot adjusted data
112+
show_var = ones(nvars, nfloats); % default: assume adjusted values are available
113+
if strncmpi(raw,'y',1)
114+
[title_added{1:nvars}] = deal([title_add, ' [raw values]']);
115+
else
116+
[title_added{1:nvars}] = deal(title_add);
117+
for v = 1:nvars
118+
% if all floats have adjusted values available for a variable,
119+
% they will be used instead of raw values
120+
has_adj = 0;
121+
for f = 1:nfloats
122+
% the "_ADJUSTED" variable usually exists, but it may not
123+
% be filled with actual values
124+
if isfield(Data.(floats{f}),[variables{v}, '_ADJUSTED']) && ...
125+
sum(isfinite(Data.(floats{f}).([variables{v}, '_ADJUSTED'])(:)))
126+
has_adj = has_adj + 1;
127+
elseif strcmpi(raw, 'no_strict')
128+
warning(['adjusted values for %s for float %s are not ',...
129+
'available;\nits values will not be shown'], ...
130+
variables{v}, floats{f});
131+
show_var(v,f) = 0;
132+
has_adj = has_adj + 1; % needed for check below
133+
else
134+
warning(['adjusted values for %s for float %s are not available,',...
135+
' showing raw values for all profiles instead'], ...
136+
variables{v}, floats{f});
137+
title_added{v} = [title_added{v}, ' [raw values]'];
138+
break
139+
end
140+
end
141+
if has_adj == nfloats
142+
variables{v} = [variables{v}, '_ADJUSTED'];
143+
end
144+
end
145+
end
146+
147+
[lon_lim, lat_lim, Data] = get_lon_lat_lims(Data);
148+
% Set lat and lon limits
149+
latlim = [lat_lim(1)-Settings.pad_lat, lat_lim(2)+Settings.pad_lat];
150+
lonlim = [lon_lim(1)-Settings.pad_lon, lon_lim(2)+Settings.pad_lon];
151+
% Adjust limits outside range to minimum and maximum limits
152+
latlim(latlim < -90) = -90;
153+
latlim(latlim > 90) = 90;
154+
% use 0..360 range if all points are near the dateline
155+
if isfield(Data.(floats{1}), 'ALT_LON')
156+
lonlim(lonlim < 0) = 0;
157+
lonlim(lonlim > 360) = 360;
158+
use_alt_lon = 1;
159+
else % using a range of -180..180
160+
lonlim(lonlim < -180) = -180;
161+
lonlim(lonlim > 180) = 180;
162+
use_alt_lon = 0;
163+
end
164+
165+
% vertical interpolation to depths with regular intervals
166+
for f = 1:nfloats
167+
Datai.(floats{f}) = depth_interp(Data.(floats{f}), qc_flags, 'raw', raw);
168+
end
169+
170+
for v = 1:nvars
171+
if ~any(show_var(v,:))
172+
fprintf('None of the specified floats have adjusted %s values, skipping the plot\n', ...
173+
variables{v})
174+
continue
175+
end
176+
[long_name, units] = get_var_name_units(variables{v});
177+
for d = 1:ndepths
178+
for f = 1:nfloats
179+
[mini,idz] = min(abs(Datai.(floats{f}).PRES(:,1) - depths(d)));
180+
if mini < 2 % interpolated depths are at 2 dbar intervals
181+
break
182+
end
183+
end
184+
if mini > 2
185+
warning('The requested depth level (%d dbar) was not found and will be skipped.', ...
186+
depths(d))
187+
continue;
188+
end
189+
f1 = figure;
190+
if isfield(Settings, 'colormap')
191+
cmap = colormap(Settings.colormap);
192+
else
193+
cmap = colormap;
194+
end
195+
geoaxes;
196+
hold on;
197+
% Set geographic limits for figure
198+
geolimits(latlim,lonlim)
199+
geobasemap grayland
200+
if ~isempty(cax)
201+
caxis(cax)
202+
end
203+
for f = 1:nfloats
204+
if ~show_var(v,f)
205+
continue;
206+
end
207+
if size(Datai.(floats{f}).(variables{v}), 1) < idz
208+
warning('Float %s did not reach %d dbar', floats{f}, ...
209+
depths(d))
210+
continue
211+
end
212+
if use_alt_lon
213+
lon{f} = Data.(floats{f}).ALT_LON(1,:);
214+
else
215+
lon{f} = Data.(floats{f}).LONGITUDE(1,:);
216+
end
217+
good_pts = ~isnan(Datai.(floats{f}).(variables{v})(idz,:));
218+
if ~isempty(good_pts)
219+
geoscatter(Data.(floats{f}).LATITUDE(1,good_pts), lon{f}(good_pts), ...
220+
sz,Datai.(floats{f}).(variables{v})(idz,good_pts), '.')
221+
caxis
222+
end
223+
end
224+
title(sprintf('%s %s at %d dbar%s', long_name, units, ...
225+
depths(d), title_added{v}), 'FontSize', 14);
226+
colorbar
227+
if ~isempty(basename)
228+
fn_png = sprintf('%s_%s_%ddbar.png', basename, variables{v}, depths(d))
229+
print(f1, '-dpng', fn_png);
230+
end
231+
end
232+
end

show_maps.m

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
function good_float_ids = show_maps(float_ids, variables, depths, varargin)
2+
% show_profiles This function is part of the
3+
% MATLAB toolbox for accessing Argo float data.
4+
%
5+
% USAGE:
6+
% good_float_ids = show_maps(float_ids, variables, depths, varargin)
7+
%
8+
% DESCRIPTION:
9+
% This an intermediary function that downloads profile(s) for the given
10+
% float(s) and calls plot_maps to create the plot(s).
11+
%
12+
% INPUTS:
13+
% float_ids : WMO ID(s) of the float(s)
14+
% variables : cell array of variable(s) or one variable as a string
15+
% depths : depth levels to show (dbar)
16+
%
17+
% OPTIONAL INPUTS:
18+
% 'caxis',[cmin cmax] : specify the minimum and maximum value to be
19+
% shown (for all variables and depths);
20+
% default: automatic scaling for each variable and depth
21+
% separately
22+
% 'float_profs',fp : cell array with per-float indices of the profiles to
23+
% be shown, as returned by select_profiles
24+
% 'png',basename: if basename is not empty, png files will be created
25+
% for all plots; the file names will be
26+
% <basename>_<variable>_<depth>dbar.png
27+
% 'qc',flags : show only values with the given QC flags (as an array)
28+
% 0: no QC was performed;
29+
% 1: good data;
30+
% 2: probably good data;
31+
% 3: probably bad data that are potentially correctable;
32+
% 4: bad data;
33+
% 5: value changed;
34+
% 6,7: not used;
35+
% 8: estimated value;
36+
% 9: missing value
37+
% default setting: 0:9 (all flags)
38+
% See Table 7 in Bittig et al.:
39+
% https://www.frontiersin.org/files/Articles/460352/fmars-06-00502-HTML-r1/image_m/fmars-06-00502-t007.jpg
40+
% 'raw',raw : plot raw, i.e., unadjusted data if set to 'yes';
41+
% default: 'no' (i.e., plot adjusted data if available)
42+
% 'no_strict': plot only adjusted data, skip floats
43+
% that have only raw data available
44+
% 'size',sz : sz (positive integer) defines the size of plotted
45+
% points (default: 200)
46+
%
47+
% OUTPUT:
48+
% good_float_ids : array of the float IDs whose Sprof files were
49+
% successfully downloaded or existed already
50+
%
51+
% AUTHORS:
52+
% H. Frenzel, J. Sharp, A. Fassbender (NOAA-PMEL), N. Buzby (UW)
53+
%
54+
% CITATION:
55+
% H. Frenzel, J. Sharp, A. Fassbender, N. Buzby, 2022. OneArgo-Mat:
56+
% A MATLAB toolbox for accessing and visualizing Argo data.
57+
% Zenodo. https://doi.org/10.5281/zenodo.6588041
58+
%
59+
% LICENSE: oneargo_mat_license.m
60+
%
61+
% DATE: JUNE 1, 2022 (Version 1.0.1)
62+
63+
global Settings;
64+
65+
% make sure Settings is initialized
66+
if isempty(Settings)
67+
initialize_argo();
68+
end
69+
70+
% assign empty arrays to the return value in case of early return
71+
good_float_ids = [];
72+
73+
if isempty(float_ids)
74+
warning('no floats specified')
75+
return
76+
end
77+
78+
% set defaults
79+
if nargin < 3
80+
warning('Usage: show_maps(float_ids, variables, depths, varargin)');
81+
return
82+
end
83+
float_profs = [];
84+
basename = [];
85+
sz = 200;
86+
varargpass= {};
87+
88+
% parse optional arguments
89+
for i = 1:2:length(varargin)-1
90+
if strcmpi(varargin{i}, 'float_profs')
91+
float_profs = varargin{i+1};
92+
elseif strcmpi(varargin{i}, 'size')
93+
if round(varargin{i+1}) > 0
94+
sz = round(varargin{i+1});
95+
else
96+
warning('size must be a positive integer')
97+
end
98+
elseif strcmpi(varargin{i}, 'png')
99+
basename = varargin{i+1};
100+
else
101+
if strcmpi(varargin{i}, 'qc')
102+
if min(varargin{i+1}) < 0 || max(varargin{i+1}) > 9
103+
warning('only QC flags 0..9 are allowed!')
104+
continue; % don't add it to varargpass
105+
end
106+
end
107+
varargpass = [varargpass, varargin{i:i+1}];
108+
end
109+
end
110+
111+
if ~strcmp(Settings.mapping, 'native')
112+
warning('This function is only implemented for the native Matlab geofunctions')
113+
return
114+
end
115+
116+
% convert requested variable to cell array if necessary and
117+
% discard unknown variables
118+
variables = check_variables(variables, 'warning', ...
119+
'unknown sensor will be ignored');
120+
121+
% if float profiles were specified, make sure that there are no empty
122+
% arrays; if so, disregard these floats
123+
if ~isempty(float_profs)
124+
no_profs = cellfun(@isempty, float_profs);
125+
if any(no_profs)
126+
warning('No profiles specified for float(s):');
127+
disp(float_ids(no_profs))
128+
float_ids(no_profs) = [];
129+
float_profs(no_profs) = [];
130+
end
131+
end
132+
133+
% download prof and Sprof files if necessary
134+
good_float_ids = download_multi_floats(float_ids);
135+
136+
if isempty(good_float_ids)
137+
warning('no valid floats found')
138+
else
139+
avail_vars = check_float_variables(good_float_ids, variables, ...
140+
'warning', 'Not available in all specified floats');
141+
tic
142+
[Data, Mdata] = load_float_data(good_float_ids, avail_vars, ...
143+
float_profs);
144+
toc
145+
plot_maps(Data, Mdata, avail_vars, depths, sz, basename, varargpass{:});
146+
end

0 commit comments

Comments
 (0)