% function plot_fit(arg1,arg2,arg3,...)
%
% Function for plotting the results of the GUISDAP fitting process.
% plot_fit reads GUISDAP results file(s), and plots any of the fitted
% parameters Ne, Te, Te/Ti, [O+] and Vi, each in a separate panel. Files
% can be named explicitly in the argument list, otherwise data is read
% from the workspace. Parameters are specified using a mask of 1's and
% 0's and the order of the parameters is as above. Missing elements at
% the end of this mask are provided by the programme.
%
% Example 1:
% plot_fit('panel',[1 1 1 0 1],[])
%
% takes GUISDAP result data from the workspace, and plots the fit values
% of Ne, Te, Te/Ti and Vi for all heights at which data was analysed.
% Data is found on the "workspace" if:
% 1) a results file has been explicitly loaded OR
% 2) after one set of data has been fitted and
% before the next set has been fitted!
%
% Example 2:
% plot_fit('panel',[1 1 1],[400 800 25])
%
% plots the fit values of Ne,Te, and Te/Ti inside the height range 400-800
% km with tickmarks every 25 km. A default tick mark spacing is provided,
% so this element of arg2 is optional.
%
% Example 3:
% plot_fit('panel',[],[400 800],'files','file.mat')
%
% plots all parameters in the range 400-800 km with default tickmark
% spacing, and data taken from "file.mat".
%
% Example 4:
% plot_fit('panel',[],[],'files','file1.mat','file2.mat')
%
% plots all parameters over the maximum height range with default spacing,
% and data is taken from the 2 files specified. The data from each is
% specified in a different colour.
%
% The keywords 'Fontname', 'Fontsize', and 'Fontweight' can be used in the
% input arguments to specify the font used for he axis text. The keyword
% 'Markersize' is used to specify the size of the marker used for each
% value. The default marker size is 4. The default font is Times-Roman,
% 10pt, Normal weight. Other fontnames are for example Helvetica,
% Palatino, Courier, Schumacher, Lucida ...
%
% Example 4: %% Set the font details explicitly ...
% plot_fit('Fontname','Helvetica',...
% 'Fontsize',11, ...
% 'Fontweight','Bold', ...
% 'MarkerSize',7);
%
% Example 5: %% Switching off the text output ...
% plot_fit(...,'NoText',...);
%
% If several files' data are to be plotted, then all points are plotted
% in the same colour (for speed) unless the option 'colour' is specifed
% in which case each file's data comes up in a different colour. The
% latter is also slower.
%
% Example 6:
% plot_fit(...,'Colour',...);
%
% Additional modifications to the plot can be made directly by accessing
% individual panels' handles, which are stored in the figure's UserData
% field e.g.
% for i=get(gcf,'UserData'), axes(i), grid on, end
%
% To create output with aspect ratio 2, do, for example,
% for i=get(gcf,'UserData'),axes(i),set(gca,'AspectRatio',[2 NaN]),end
%
% To obtain a hardcopy use the MATLAB "print" command. Do not make
% your own alterations. In the event of difficulty, contact:
% nickgjg@eiscat.ag.rl.ac.uk OR n.gazey@rl.ac.uk
function plot_fit(arg1, arg2, arg3, arg4, arg5, ...
arg6, arg7, arg8, arg9, arg10, ...
arg11, arg12, arg13, arg14, arg15, ...
arg16, arg17, arg18, arg19, arg20)
global r_param r_error r_dp r_status r_h ch_el d_time
gcf1=gcf;
global name_expr name_site
if sum(get(gcf1,'color'))>2
white='k';
else
white='w';
end
%% Except for composition, the order of the other
%% fitted parameters is as in the array r_param.
%% If composition is desired, the information in
%% the 4th column of r_param is replaced by the
%% composition information, and the various masks
%% are used to access the correct column(s)......
NE = [1 0 0 0 0]; %% Electron density
TI = [0 1 0 0 0]; %% Ion temperature
TR = [0 0 1 0 0]; %% Te/Ti
CP = [0 0 0 1 0]; %% Composition
VI = [0 0 0 0 1]; %% Ion velocity
maxpars = 5;
labels = str2mat('N_e/10^{11}',...
'T_i',...
'T_e/T_i',...
'[O^+]/N_e',...
'V_i');
colours = ['y'; 'm'; 'c'; 'r'; 'g'; 'b'; white];
mask = [];
hght = [];
file = [];
font_name = 'Times'; %% Default font ...
font_size = 10; %% Default font size ...
font_wght = 'Normal'; %% Default font weight ...
marker_size = 4; %% Default marker size ...
write_text = 1; %% Whether text is written ...
colour = 0; %% Faster, plain colour option is the default ...
if (nargin==0)
mask = ones(1,maxpars);
%% hght array not specified yet ...
npanels = maxpars;
panels = zeros(npanels,1);
nfiles = 1;
use_ws = 1; %% Use workspace variables
else
%% Parse the input arguments ...
j=1; m=[]; h=[]; f=[];
while (j <= nargin)
if eval(['(strcmp(arg' int2str(j) ',''panel'')' ...
' | strcmp(arg' int2str(j) ',''Panel''))'])
%% Each panel specified separately ...
j = j+1; if (j+1 > nargin)
error('Usage of (1)')
else
eval(['m=arg' int2str(j) ';'])
j = j+1;
eval(['h=arg' int2str(j) ''';'])
end
elseif eval(['(strcmp(arg' int2str(j) ',''files'')' ...
' | strcmp(arg' int2str(j) ',''Files'')' ...
' | strcmp(arg' int2str(j) ',''file'')' ...
' | strcmp(arg' int2str(j) ',''File''))'])
%% Files to be read ...
j = j+1; while (j <= nargin)
if (j > nargin)
break
else
eval(['f=str2mat(f,arg' int2str(j) ');'])
end
j = j+1; if (j <= nargin)
if eval(['(isstr(arg' int2str(j) ') ' ...
'& (strcmp(arg' int2str(j) ',''Files'') ' ...
' | strcmp(arg' int2str(j) ',''Fontsize'') ' ...
' | strcmp(arg' int2str(j) ',''FontSize'') ' ...
' | strcmp(arg' int2str(j) ',''fontsize'') ' ...
' | strcmp(arg' int2str(j) ',''Fontweight'') ' ...
' | strcmp(arg' int2str(j) ',''FontWeight'') ' ...
' | strcmp(arg' int2str(j) ',''fontweight'') ' ...
' | strcmp(arg' int2str(j) ',''Fontname'') ' ...
' | strcmp(arg' int2str(j) ',''FontName'') ' ...
' | strcmp(arg' int2str(j) ',''fontname'') ' ...
' | strcmp(arg' int2str(j) ',''Notext'') ' ...
' | strcmp(arg' int2str(j) ',''NoText'') ' ...
' | strcmp(arg' int2str(j) ',''notext'') ' ...
' | strcmp(arg' int2str(j) ',''Markersize'') ' ...
' | strcmp(arg' int2str(j) ',''MarkerSize'') ' ...
' | strcmp(arg' int2str(j) ',''markersize'') ' ...
' | strcmp(arg' int2str(j) ',''Colour'') ' ...
' | strcmp(arg' int2str(j) ',''colour'') ' ...
' | strcmp(arg' int2str(j) ',''Color'') ' ...
' | strcmp(arg' int2str(j) ',''color'') ' ...
' | strcmp(arg' int2str(j) ',''Panel'') ' ...
' | strcmp(arg' int2str(j) ',''panel'')))'])
j = j-1;
break
end
end
end
%% Note that str2mat() gives "file" an extra
%% row! Get rid of it here before it disrupts
%% later on.
f(1,:) = [];
elseif eval(['(strcmp(arg' int2str(j) ',''Colour'')' ...
' | strcmp(arg' int2str(j) ',''colour'')' ...
' | strcmp(arg' int2str(j) ',''color'')' ...
' | strcmp(arg' int2str(j) ',''Color''))'])
%% Flag to allow the slower colour plotting version ...
colour = 1;
elseif eval(['(strcmp(arg' int2str(j) ',''Markersize'')' ...
' | strcmp(arg' int2str(j) ',''MarkerSize'')' ...
' | strcmp(arg' int2str(j) ',''markersize''))'])
%% Set the fontsize explicitly ...
j = j+1; if (j > nargin)
error('Usage of Markersize')
else
eval(['marker_size=arg' int2str(j) ';'])
end
elseif eval(['(strcmp(arg' int2str(j) ',''NoText'')' ...
' | strcmp(arg' int2str(j) ',''Notext'')' ...
' | strcmp(arg' int2str(j) ',''notext''))'])
write_text=0;
elseif eval(['(strcmp(arg' int2str(j) ',''Fontsize'')' ...
' | strcmp(arg' int2str(j) ',''FontSize'')' ...
' | strcmp(arg' int2str(j) ',''fontsize''))'])
%% Set the fontsize explicitly ...
j = j+1; if (j > nargin)
error('Usage of Fontsize')
else
eval(['font_size=arg' int2str(j) ';'])
end
elseif eval(['(strcmp(arg' int2str(j) ',''Fontweight'')' ...
' | strcmp(arg' int2str(j) ',''FontWeight'')' ...
' | strcmp(arg' int2str(j) ',''fontweight''))'])
%% Set the fontweight explicitly ...
j = j+1; if (j > nargin)
error('Usage of Fontweight')
else
eval(['font_wght=arg' int2str(j) ';'])
end
elseif eval(['(strcmp(arg' int2str(j) ',''Fontname'')' ...
' | strcmp(arg' int2str(j) ',''FontName'')' ...
' | strcmp(arg' int2str(j) ',''fontname''))'])
%% Set the fontname explicitly ...
j = j+1; if (j > nargin)
error('Usage of Fontname')
else
eval(['font_name=arg' int2str(j) ';'])
end
end
j = j + 1;
end
mask = m;
hght = h;
file = f;
%% Check parameter mask ...
if isempty(mask)
mask = ones(1,maxpars);
disp('Note: Supplying default parameter mask .....')
elseif (length(mask) > maxpars)
%% Truncate to maximum mask length ...
mask(maxpars+1:length(mask)) = [];
disp(['Note: Using parameter mask ' int2str(mask) ' .....'])
elseif (length(mask) < maxpars)
%% Fill out missing elements ...
mask(length(mask)+1:maxpars) = zeros(1,maxpars - length(mask));
disp(['Note: Using parameter mask ' int2str(mask) ' .....'])
end
npanels = length(find(mask));
panels = zeros(npanels,1);
%% Check that any specified files exist ... there may
%% be no data on the workspace, so do this first. If
%% the files exist, assume initially that they are valid.
if ~isempty(file)
togo=[]; for k = 1:size(file,1)
if (fopen(canon(file(k,:),0)) < 0)
warning(['Cannot open ' file(k,:) '... '])
togo = [togo k];
end
end
if ~isempty(togo), file(togo,:)=[]; end
end
%% If invalid files were specified, or no files were
%% specified at all, then we use workspace variables
if isempty(file)
use_ws = 1;
nfiles = 1;
else
use_ws = 0 ;
nfiles = size(file,1);
end
%% Check the height array dimensions. Actual values
%% are checked and default values given only after
%% the initial argument checking loop, once it is
%% clear whence the variables are to come.
if ~isempty(hght)
hghtcheck1 = size(hght(~isnan(hght)),1);
if (hghtcheck1 < 2)
error(['Upper and lower height ' ...
'limits for each panel must be specified'])
elseif (hghtcheck1 > 3)
warning(['Programme requires only upper and lower ' ...
'height limits, and an optional tickmark spacing'])
hght(3:size(hght,1),:) = [];
end
hghtcheck2 = size(hght,2);
if (hghtcheck2 > 1)
disp('Note: height array should be 1-D ...')
hght(:,2:hghtcheck2) = [];
end
end
end %% End of argument checks .... see below for hght check
%% If data comes from files, construct the data variables first
if (~use_ws)
disp('Note: Obtaining data variables from specified file(s)')
param=[]; err=[]; status=[]; h=[]; dp=[]; el=[]; time=[];
name=[]; site=[];
for k = 1 : nfiles
load(canon(file(k,:),0))
param = pad(param,r_param,NaN);
lr = size(r_param,2);
err = pad(err,r_error(:,1:lr),NaN);
status= pad(status,r_status,NaN);
h = pad(h,r_h,NaN);
dp = pad(dp,r_dp,NaN);
el = pad(el,r_el,NaN);
time = [time;r_time];
name = str2mat([name; name_expr]);
site = str2mat([site; name_site]);
end
else
if (isempty(r_param) | isempty(r_error) | isempty(r_status) | ...
isempty(r_h) | isempty(r_dp) | isempty(d_time))
disp('Note: There are no result variables on the workspace')
return
% else
% disp('Note: Using variables on the workspace')
end
param = r_param;
lr = size(r_param,2);
err = r_error(:,1:lr);
status= r_status;
h = r_h;
dp = r_dp;
el = ch_el(1);
time = d_time;
name = name_expr;
site = name_site;
end
%% Check that variables have been declared as global outside
%% this function i.e. whether they are really available!
if (isempty(param) | isempty(err) | isempty(dp) | isempty(status) | ...
isempty(h) | isempty(el) | isempty(time))
disp('Error: (Global) variable set incomplete .....')
disp('*****: Check r_param,r_error,r_status,r_dp,r_h,ch_el & d_time')
return
end
check = size(param,1); %% Check their dimensions ....
if ((size(err,1) ~= check) | ...
(size(h,1) ~= check) | ...
(size(status,1)~= check) | ...
(size(dp,1) ~= check))
error(['r_error, r_h, r_status, r_dp and r_param ' ...
'must have the same no. rows'])
end
%% Scale NE if necessary ... and replace fourth column of r_param
%% with composition information if the latter is desired ....
if (use_ws)
if any(mask & NE)
param(:,1) = param(:,1)/1e11;
err(:,1) = err(:,1)/1e11;
end
if any(mask & CP)
%% Replace fourth column (coll. freq.)
%% with composition information.
param(:,4) = dp;
err(:,4) = duprow(NaN,length(dp));
end
else
if any(mask & NE)
ind = dupcol2(1,nfiles,5);
param(:,ind) = param(:,ind)/1e11;
err(:,ind) = err(:,ind)/1e11;
end
if any(mask & CP)
%% Replace fourth column (coll. freq.)
%% with composition information.
ind = dupcol2(4,nfiles,5);
[r,c] = size(dp);
param(:,ind) = dp;
err(:,ind) = ones(r,c).*NaN;
end
end
%% Round altitude limits up and down to nearest 10 km ...
tmp = r_h(~isnan(r_h));
hi = min(min(tmp)); hi = hi - rem(hi,10);
hf = max(max(tmp)); hf = hf - rem(hf,10) + 10;
all_hght = [hi hf]';
%% Supply default height values here, in case hght is
%% still empty. Otherwise, sieve out Inf's and replace
%% with the respective maximum/minimum height limit.
if isempty(hght)
hght = all_hght;
elseif any(any(isinf(hght)))
[hghtcheck1,hghtcheck2] = size(hght);
%% 1) Replace 'inf' lower limit with all_hght(1) ...
tmp = find(isinf(hght(1,:)));
if ~isempty(tmp)
hght(1,tmp) = dupcol(all_hght(1),length(tmp));
end
%% 2) Replace 'inf' upper limit with all_hght(2) ...
tmp = find(isinf(hght(2,:)));
if ~isempty(tmp)
hght(2,tmp) = dupcol(all_hght(2),length(tmp));
end
%% 3) Replace 'inf' tickmarkangaben with NaN's ...
if (hghtcheck1 > 2)
tmp = find(isinf(hght(3,:)));
if ~isempty(tmp)
hght(3,tmp) = dupcol(NaN,length(tmp));
end
end
end
if (length(hght(~isnan(hght))) < 3)
hdiff = hght(2)-hght(1);
if (hdiff > 1000)
dh1 = 500;
elseif (hdiff > 100)
dh1 = 200;
elseif (hdiff > 10)
dh1 = 20;
else
dh1 = 2;
end
hght = [hght(1);hght(2);dh1];
end
%% Determine which elements of each matrix are real fits
%% and the corresponding ranges. If data is pulled from
%% files, then the fits in each file, and the corresponding
%% range values may all be different.
if (use_ws)
%% Indices of fits and no-fits ...
fits = find(status==0 & h>=hght(1) & h<=hght(2));
nofits = find(status==1 & h>=hght(1) & h<=hght(2));
%% Heights of fitted and unfitted data ...
hf = h(fits);
hn = h(nofits);
%% Data ... (all)
err_plus = param + err;
err_minus = param - err;
else
fits = find(status==0 & h>=hght(1) & h<=hght(2));
nofits = find(status==1 & h>=hght(1) & h<=hght(2));
%% Heights of fitted and unfitted data ...
hf = h(fits);
hn = h(nofits);
%% Data ... (all)
err_plus = param + err;
err_minus = param - err;
end
%% Underlying range units .....
hgrid = (hght(1):hght(2))';
%% Used for placing range major tickmarks .....
hmajor = hgrid(find(rem(hgrid,hght(3))==0));
%% Range labels ... in km.
hlabel = makelabels(hmajor);
%% Now plot the picture
goodgap = 0.05;
clf(gcf1), set(gcf1,'Resize','On','Name','plot_fit')
if (~use_ws)
%% Since we cannot use sparse matrices to index
%% other arrays, input from several files is
%% handled quickly by decomposing the "param"
%% array into a single column matrix, and finding
%% the right indices, knowing that param has lr
%% columns, and what the desired parameters are.
q = size(status,1);
%% 1) Fits ...................
fm = remscale(fits,q);
fn = (fits-fm)/q;
foo= fn*lr*q + fm;
%% 2) No-fits ................
nm = remscale(nofits,q);
nn = (nofits-nm)/q;
noo= nn*lr*q + nm;
end
%% Step through the different parameters ...
for i = 1 : npanels
index = find(mask);
panelmask = zeros(1,maxpars);
panelmask(index(i)) = 1;
dx = (1-goodgap-(npanels*0.75*goodgap))/npanels;
x0 = (1.25*goodgap) + (i-1)*dx + (i-1)*goodgap*0.75;
y0 = (nfiles+4)*goodgap*0.5;
dy = 1- y0 -(3*goodgap*0.5);
panels(i) = axes(...
'Units','normal',...
'Position',[x0 y0 dx dy],...
'Box','On',...
'Visible','On');
if (use_ws)
%% Desired parameter in column index(i) ...
%% Fitted values ...
fpar = param(fits,index(i));
fupper = err_plus(fits,index(i));
flower = err_minus(fits,index(i));
%% Unfitted values ...
npar = param(nofits,index(i));
nupper = err_plus(nofits,index(i));
nlower = err_minus(nofits,index(i));
%% The plot ...
p = plot(fpar,hf,[white 'o'],[flower fupper]',[hf hf]',[white '-'], ...
npar,hn,[white '*'],[nlower nupper]',[hn hn]',[white '-']);
set(p,'Markersize',marker_size);
else
%% Use "foo" and "noo" to take into account
%% the particular parameter being plotted.
fo = foo + (index(i)-1)*q;
no = noo + (index(i)-1)*q;
if (colour==1)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This does a slow job but nevertheless plots
%% each file's values in a different colour.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
col = unique(nn); for c=col'
hnn = hn(nn==c);
npar = param(no(nn==c));
nupper = err_plus(no(nn==c));
nlower = err_minus(no(nn==c));
colname = colours(c+1);
eval(['v =''' colname 'o'';'])
eval(['r =''' colname '*'';'])
eval(['l =''' colname '-'';'])
p = plot(npar,hnn,r,[nlower nupper]',[hnn hnn]',l);
set(p,'Markersize',marker_size)
hold on
end
else
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This treats the whole parameter matrix as a
%% single column and plots all fits/no-fits
%% together, regardless of which file they came
%% from. This is MUCH quicker than the alternative
%% .... but everything comes out in the same colour.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fpar = param(fo);
fupper = err_plus(fo);
flower = err_minus(fo);
npar = param(no);
nupper = err_plus(no);
nlower = err_minus(no);
%% The plot ................
col = rem(1,length(colours));
if (col==0), col=length(colours); end
colname = colours(col);
eval(['v =''' colname 'o'';'])
eval(['r =''' colname '*'';'])
eval(['l =''' colname '-'';'])
p = plot(fpar,hf,v,[flower fupper]',[hf hf]',l, ...
npar,hn,r,[nlower nupper]',[hn hn]',l);
set(p,'Markersize',marker_size)
end
end
set(gca,'ytick',hmajor, ...
'ylim',[hght(1) hght(2)], ...
'Yticklabel',[], ...
'Fontname',font_name, ...
'Fontsize',font_size, ...
'Fontweight',font_wght)
if any(panelmask & TR) %% Line indicating Te/Ti = 1 ...
line([1 1]',[hght(1) hght(2)], ...
'LineStyle',':', ...
'Color',white)
end
if any(panelmask & VI) %% Line indicating zero velocity ...
line([0 0]',[hght(1) hght(2)], ...
'LineStyle',':', ...
'Color',white)
end
title(labels(index(i),:))
end
set(gcf1,'currentaxes',panels(1)), set(gca,'Yticklabel',hlabel)
%% Store the panels handles for subsequent use ....
if sum(get(gcf1,'UserData'))~=4
disp(['Note: Individual panel handles are obtained using: ' ...
'get(gcf1,''UserData'')'])
set(gcf1,'UserData',panels'); %% ROW OF PANEL HANDLES ...
end
%% Put time string(s) in, indicating when dump was made ...
axes('Units','Normal','Position',[0 0 1 1],'Visible','Off');
if (use_ws & write_text)
fmt = ['%4d-%02d-%02d %02d%02d:%02.0f - '...
'%4d-%02d-%02d %02d%02d:%02.0f '...
'(El=%.1f deg) [%s:%s]'];
tstrg = sprintf(fmt,time(1,:),time(2,:),...
el,name_expr,name_site);
t = text(goodgap,goodgap/2,tstrg);
set(t,'VerticalAlignment','Baseline', ...
'Fontname',font_name, ...
'Fontsize',font_size, ...
'Fontweight',font_wght');
elseif (write_text)
fmt = ['File %d: '...
'%4d-%02d-%02d %02d%02d:%02.0f - '...
'%4d-%02d-%02d %02d%02d:%02.0f '...
'(El=%.1f deg) [%s:%s]'];
for k = 1:nfiles
tstrg = sprintf(fmt,k,time(2*k-1,:),time(2*k,:),...
r_el,name(k,:),site(k,:));
t=text(goodgap,k*(0.6*goodgap),tstrg);
set(t,'VerticalAlignment','Baseline',...
'Fontname',font_name, ...
'Fontsize',font_size, ...
'Fontweight',font_wght');
end
end
function a = remscale(b,factor)
a = rem(b,factor);
if any(a==0)
a(a==0) = dupcol(factor,length(find(a==0)));
end