[Dart-dev] [4251] DART/trunk: read_obs_netcdf no longer has a 'maxQC' argument, nor will it

nancy at ucar.edu nancy at ucar.edu
Wed Feb 3 13:50:30 MST 2010


Revision: 4251
Author:   thoar
Date:     2010-02-03 13:50:30 -0700 (Wed, 03 Feb 2010)
Log Message:
-----------
read_obs_netcdf  no longer has a 'maxQC' argument, nor will it
return observations subsetted based on maxQC. The routine is more
useful if it returns all the observations and you can query based
on any/all QC value(s).

The plotting routines now have a 'twoup' flag so you can plot the
observations above and the QC values below.

The linked_observations() function now plots a scatterplot of
the observation value vs. prior ensemble mean (for example).

GetNCindices is one step closer to recognizing WRF coordinate variables.

Modified Paths:
--------------
    DART/trunk/diagnostics/matlab/linked_observations.m
    DART/trunk/diagnostics/matlab/plot_evolution.m
    DART/trunk/diagnostics/matlab/plot_obs_netcdf.m
    DART/trunk/diagnostics/matlab/plot_obs_netcdf_diffs.m
    DART/trunk/diagnostics/matlab/read_obs_netcdf.m
    DART/trunk/matlab/DART.m
    DART/trunk/matlab/GetNCindices.m
    DART/trunk/matlab/get_qc_index.m

-------------- next part --------------
Modified: DART/trunk/diagnostics/matlab/linked_observations.m
===================================================================
--- DART/trunk/diagnostics/matlab/linked_observations.m	2010-02-03 18:02:11 UTC (rev 4250)
+++ DART/trunk/diagnostics/matlab/linked_observations.m	2010-02-03 20:50:30 UTC (rev 4251)
@@ -1,13 +1,6 @@
-function linked_observations(obsmat,obs)
-% linked_observations(obs)
-%
-% obs is a structure with the following required components
-%
-% obs.lons	longitudes of the observations
-% obs.lats	latitudes of the observations
-% obs.z		vertical level (depth) of the observations
-% obs.obs	observation values
-% obs.qc	observation DART QC code
+function linked_observations(obs)
+% linked_observations(obs) is a helper function for link_obs.m
+% linked_observations is never meant to be called directly.
 
 %% DART software - Copyright \xA9 2004 - 2010 UCAR. This open source software is
 % provided by UCAR, "as is", without charge, subject to all terms of use at
@@ -19,14 +12,46 @@
 % $Revision$
 % $Date$
 
+% obs has components (for example):
+%            fname: '/ptmp/thoar/POP/CAM/POP8/obs_sequence_001.nc'
+%    ObsTypeString: 'RADIOSONDE_TEMPERATURE'
+%    ObsCopyString: 'NCEP BUFR observation'
+%       CopyString: 'prior ensemble mean'
+%         QCString: 'DART quality control'
+%           region: [0 360 -90 90 -Inf Inf]
+%          verbose: 1
+%       timestring: [2x20 char]
+%             lons: [794x1 double]
+%             lats: [794x1 double]
+%                z: [794x1 double]
+%              obs: [794x1 double]
+%             Ztyp: [794x1 int32]
+%             keys: [794x1 int32]
+%             time: [794x1 double]
+%               qc: [794x1 int32]
+%         colnames: {1x9 cell}
+%         lonindex: 1
+%         latindex: 2
+%           zindex: 3
+%         obsindex: 4
+%        copyindex: 5
+%          qcindex: 6
+%         keyindex: 7
+%        timeindex: 8
+%         indindex: 9
+
+global obsmat
+
 % Create figure
 %figure1 = figure('XVisual',...
 %    '0x24 (TrueColor, depth 24, RGB mask 0xff0000 0xff00 0x00ff)',...
 %    'Renderer','OpenGL');
-figure1 = figure(1); clf(figure1);;
+figure1 = figure(1); clf(figure1);
 
-%% Create axes for 3D plot
-axes0 = axes('Parent',figure1,'OuterPosition',[0 0 1 0.90],'FontSize',12);
+%% Create axes for 3D scatterplot
+% should figure out how to query the vertical coordinate to determine
+% direction of the Z axis ... 
+axes0 = axes('Parent',figure1,'OuterPosition',[0 0 1 0.90],'FontSize',18);
 view(axes0,[-37.5 30]);
 grid(axes0,'on');
 hold(axes0,'all');
@@ -35,16 +60,18 @@
 ystring = sprintf('obsmat(:,%d)',obs.latindex);
 zstring = sprintf('obsmat(:,%d)',obs.zindex  );
 
-h0 = scatter3(obsmat(:,obs.lonindex), obsmat(:,obs.latindex), obsmat(:,obs.zindex), ...
+scatter3(obsmat(:,obs.lonindex), obsmat(:,obs.latindex), obsmat(:,obs.zindex), ...
              'Parent',axes0,'DisplayName','observation locations', ...
              'XDataSource',xstring, ...
              'YDataSource',ystring, ...
              'ZDataSource',zstring);
 
 worldmap('light');
-xlabel('longitude');
-ylabel('latitude');
-zlabel('depth');
+
+xlabel(obs.colnames{obs.lonindex});
+ylabel(obs.colnames{obs.latindex});
+zlabel(obs.colnames{obs.zindex});
+
 h = title({obs.ObsTypeString, ...
       sprintf('%s ---> %s',obs.timestring(1,:),obs.timestring(2,:)) });
 set(h,'Interpreter','none')
@@ -55,28 +82,29 @@
 figure2 = figure(2); clf(figure2); orient tall; wysiwyg
 
 %% Create axes for time VS. QC
-axes4 = axes('Parent',figure2,'OuterPosition',[0 0.80 1 0.175]);
+axes4 = axes('Parent',figure2,'OuterPosition',[0 0.80 1 0.175],'FontSize',14);
 set(axes4,'XAxisLocation','top')
 box(axes4,'on');
 hold(axes4,'all');
 
 xstring = sprintf('obsmat(:,%d)',obs.timeindex);
 ystring = sprintf('obsmat(:,%d)',obs.qcindex);
-h4 = scatter(obsmat(:,obs.timeindex),obsmat(:,obs.qcindex),'Parent',axes4, ...
+scatter(obsmat(:,obs.timeindex),obsmat(:,obs.qcindex),'Parent',axes4, ...
              'DisplayName','time vs qc', ...
              'XDataSource',xstring, ...
              'YDataSource',ystring);
 datetick(axes4,'x',6);
-ylabel(obs.QCString);
+ylabel(obs.colnames{obs.qcindex});
 
 %% Create axes for observation index VS. time 
-axes3 = axes('Parent',figure2,'OuterPosition',[0 0.575 1 0.175]);
+%axes3 = axes('Parent',figure2,'OuterPosition',[0 0.575 1 0.175]);
+axes3 = axes('Parent',figure2,'OuterPosition',[0 0.600 1 0.2],'FontSize',14);
 box(axes3,'on');
 hold(axes3,'all');
 
 xstring = sprintf('obsmat(:,%d)',obs.timeindex);
 ystring = sprintf('obsmat(:,%d)',obs.indindex);
-h3 = scatter(obsmat(:,obs.timeindex),obsmat(:,obs.indindex),'Parent',axes3, ...
+scatter(obsmat(:,obs.timeindex),obsmat(:,obs.indindex),'Parent',axes3, ...
              'DisplayName','time vs key', ...
              'XDataSource',xstring, ...
              'YDataSource',ystring);
@@ -84,37 +112,70 @@
 datetick(axes3,'x',6);
 
 %% Create axes for observation index VS. linked list key
-axes2 = axes('Parent',figure2,'OuterPosition',[0.0 0.400 1 0.15]);
+%axes2 = axes('Parent',figure2,'OuterPosition',[0.0 0.375 1 0.2]);
+axes2 = axes('Parent',figure2,'OuterPosition',[0.0 0.35 1 0.25],'FontSize',14);
 box(axes2,'on');
 hold(axes2,'all');
 
 xstring = sprintf('obsmat(:,%d)',obs.indindex);
 ystring = sprintf('obsmat(:,%d)',obs.keyindex);
-h2 = scatter(obsmat(:,obs.indindex),obsmat(:,obs.keyindex),'Parent',axes2, ...
+scatter(obsmat(:,obs.indindex),obsmat(:,obs.keyindex),'Parent',axes2, ...
              'DisplayName','count vs key', ...
              'XDataSource',xstring, ...
              'YDataSource',ystring);
 xlabel('obs count');
 ylabel('key');
 
-%% Create axes for QC vs. ObsVal scatterplot
-axes1 = axes('Parent',figure2,'Position',[0.05 0.05 0.6 0.25]);
+%% Create axes for ObsVal vs. QC scatterplot
+axes1 = axes('Parent',figure2,'Position',[0.05 0.05 0.6 0.25],'FontSize',14);
 box(axes1,'on');
 hold(axes1,'all');
 
 xstring = sprintf('obsmat(:,%d)',obs.obsindex);
 ystring = sprintf('obsmat(:,%d)',obs.qcindex);
-h1 = scatter(obsmat(:,obs.obsindex),obsmat(:,obs.qcindex),'Parent',axes1, ...
+scatter(obsmat(:,obs.obsindex),obsmat(:,obs.qcindex),'Parent',axes1, ...
              'DisplayName','obs vs qc', ...
              'XDataSource',xstring, ...
              'YDataSource',ystring);
-xlabel(obs.CopyString);
-title(obs.QCString);
+xlabel( obs.colnames{obs.obsindex});
+h = title(  obs.ObsTypeString);
+set(h,'Interpreter','none');
+LabelQC(obs.colnames{obs.qcindex}, obs.qc)
 
+refreshdata
+linkdata on
 
-LabelQC(obs.QCString, obs.qc)
+%% Create axes for observation vs ensemble
+% This figure is most useful when all the 'bad' obs have been
+% replaced by Matlab's NAN so as not to blow the scale.
+% The idea is - if both copies 'match', they line up on the diagonal.
 
+figure3 = figure(3); clf(figure3);
 
+axes5 = axes('Parent',figure3,'OuterPosition',[0 0 1 0.95],'FontSize',18);
+grid(axes5,'on');
+hold(axes5,'all');
+
+xstring = sprintf('obsmat(:,%d)',obs.obsindex);
+ystring = sprintf('obsmat(:,%d)',obs.copyindex);
+
+scatter(obsmat(:,obs.obsindex), obsmat(:,obs.copyindex), ...
+             'Parent',axes5,'DisplayName','copy1 v copy2', ...
+             'XDataSource',xstring, ...
+             'YDataSource',ystring);
+
+xlabel(obs.colnames{obs.obsindex});
+ylabel(obs.colnames{obs.copyindex});
+h = title({obs.ObsTypeString, ...
+      sprintf('%s ---> %s',obs.timestring(1,:),obs.timestring(2,:)) });
+set(h,'Interpreter','none');
+
+axlims = [min(axis) max(axis) min(axis) max(axis)];
+axis(axlims)
+plot(axes5,[min(axis) max(axis)],[min(axis) max(axis)],'k-')
+
+%% thats it folks
+
 refreshdata
 linkdata on
 
@@ -148,13 +209,14 @@
 
       qcvals  = unique(qcarray);
       qccount = zeros(size(qcvals));
+      s = cell(length(qcvals),1);
       for i = 1:length(qcvals)
          qccount(i) = sum(qcarray == qcvals(i));
          s{i} = sprintf('%d - %s %d obs',qcvals(i), dartqc_strings{qcvals(i)+1}, qccount(i));
       end
 
       set(gca,'YTick',qcvals,'YAxisLocation','right')
-      set(gca,'YTickLabel',char(s))
+      set(gca,'YTickLabel',char(s{:}),'FontSize',12)
 
    otherwise,
       str = sprintf('no way to interpret values of %s',strtrim(QCString));

Modified: DART/trunk/diagnostics/matlab/plot_evolution.m
===================================================================
--- DART/trunk/diagnostics/matlab/plot_evolution.m	2010-02-03 18:02:11 UTC (rev 4250)
+++ DART/trunk/diagnostics/matlab/plot_evolution.m	2010-02-03 20:50:30 UTC (rev 4251)
@@ -217,7 +217,7 @@
       mean_post  = NaN;
    end
 
-   string_guess = sprintf('guess:    mean=%.5g', mean_prior);
+   string_guess = sprintf('forecast: mean=%.5g', mean_prior);
    string_analy = sprintf('analysis: mean=%.5g', mean_post);
 
    % Plot the requested quantity on the left axis.

Modified: DART/trunk/diagnostics/matlab/plot_obs_netcdf.m
===================================================================
--- DART/trunk/diagnostics/matlab/plot_obs_netcdf.m	2010-02-03 18:02:11 UTC (rev 4250)
+++ DART/trunk/diagnostics/matlab/plot_obs_netcdf.m	2010-02-03 20:50:30 UTC (rev 4251)
@@ -1,5 +1,5 @@
 function obsstruct = plot_obs_netcdf(fname, ObsTypeString, region, CopyString, ...
-                                     QCString, maxQC, verbose)
+                                     QCString, maxQC, verbose, twoup)
 %% plot_obs_netcdf will plot the locations and values of the observations in a DART netcdf file.
 %     any observations with a QC value greater than 'maxgoodQC' will get
 %     plotted on a separate figure ... color-coded to its QC value, not the
@@ -15,11 +15,10 @@
 % QCString      = 'DART quality control';
 % maxgoodQC     = 2;
 % verbose       = 1;   % anything > 0 == 'true'
+% twoup         = 1;   % anything > 0 == 'true'
 %
-% bob = plot_obs_netcdf(fname, ObsTypeString, region, CopyString, QCString, maxgoodQC, verbose);
+% bob = plot_obs_netcdf(fname, ObsTypeString, region, CopyString, QCString, maxgoodQC, verbose, twoup);
 %
-% view(0,90);   % for a traditional '2D' plot
-%
 %--------------------------------------------------
 % EXAMPLE 2: plotting all the observation types 
 %--------------------------------------------------
@@ -30,8 +29,9 @@
 % QCString      = 'WOD QC';
 % maxgoodQC     = 0;
 % verbose       = 1;   % anything > 0 == 'true'
+% twoup         = 1;   % anything > 0 == 'true'
 %
-% bob = plot_obs_netcdf(fname, ObsTypeString, region, CopyString, QCString, maxgoodQC, verbose);
+% bob = plot_obs_netcdf(fname, ObsTypeString, region, CopyString, QCString, maxgoodQC, verbose, twoup);
 
 %% DART software - Copyright \xA9 2004 - 2010 UCAR. This open source software is
 % provided by UCAR, "as is", without charge, subject to all terms of use at
@@ -47,11 +47,54 @@
    error('%s does not exist.',fname)
 end
 
+if ( twoup > 0 ) 
+   clf; orient tall
+   positions = [0.1, 0.55, 0.8, 0.35 ; ...
+                0.1, 0.10, 0.8, 0.35 ; ...
+                0.1, 0.02, 0.8, 0.08];
+else
+   clf; orient landscape
+   positions = [0.1, 0.20, 0.8, 0.65 ; ...
+                0.1, 0.20, 0.8, 0.65 ; ...
+                0.1, 0.05, 0.8, 0.10];
+end
+
 %% Read the observation sequence
 
 obsstruct = read_obs_netcdf(fname, ObsTypeString, region, ...
-                    CopyString, QCString, maxQC, verbose);
+                    CopyString, QCString, verbose);
 
+% subset based on qc value
+
+if ( (~ isempty(obsstruct.qc)) && (~ isempty(maxQC)) )
+
+   inds = find(obsstruct.qc > maxQC);
+
+   obsstruct.numflagged = length(inds);
+
+   if (~isempty(inds))
+       flaggedobs.lons = obsstruct.lons(inds);
+       flaggedobs.lats = obsstruct.lats(inds);
+       flaggedobs.Ztyp = obsstruct.Ztyp(inds);
+       flaggedobs.z    = obsstruct.z(   inds);
+       flaggedobs.obs  = obsstruct.obs( inds);
+       flaggedobs.qc   = obsstruct.qc(  inds);
+   end
+
+   fprintf('Removing %d obs with a %s value greater than %f\n', ...
+                length(inds), QCString, maxQC)
+
+   inds = find(obsstruct.qc <= maxQC);
+
+   bob = obsstruct.lons(inds); obsstruct.lons = bob;
+   bob = obsstruct.lats(inds); obsstruct.lats = bob;
+   bob = obsstruct.Ztyp(inds); obsstruct.Ztyp = bob;
+   bob = obsstruct.z(   inds); obsstruct.z    = bob;
+   bob = obsstruct.obs( inds); obsstruct.obs  = bob;
+   bob = obsstruct.qc(  inds); obsstruct.qc   = bob;
+
+end
+
 %% Create graphic with area-weighted symbols for the good observations.
 %  It has happened that there have been zero good observations in a file.
 
@@ -70,14 +113,14 @@
    fprintf('There are no ''good'' observations to plot\n')
 else
 
-   figure(gcf+1); clf
+   subplot('position',positions(1,:))
 
    % choose a symbol size based on the number of obs to plot.
 
-   if (length(obsstruct.obs) < 1000) 
+   if (length(obsstruct.obs) > 1000) 
       pstruct.scalearray = scaleme(obsstruct.obs, 36);
    else
-      pstruct.scalearray = 50.0 * ones(size(obsstruct.obs));
+      pstruct.scalearray = 128.0 * ones(size(obsstruct.obs));
    end
    pstruct.clim   = [min(obsstruct.obs) max(obsstruct.obs)];
    pstruct.str2   = sprintf('%s (%d locations)',obsstruct.CopyString,length(obsstruct.obs));
@@ -89,19 +132,19 @@
       pstruct.axis = [xmin xmax ymin ymax zmin zmax];
       pstruct.str1 = sprintf('%s level (%.2f - %.2f)',obsstruct.ObsTypeString,zmin,zmax);
 
-      plot_3D(obsstruct, pstruct)
+      plot_3D(obsstruct, pstruct);
 
    else
 
       pstruct.axis = [xmin xmax ymin ymax];
       pstruct.str1 = sprintf('%s',obsstruct.ObsTypeString);
 
-      plot_2D(obsstruct, pstruct)
+      plot_2D(obsstruct, pstruct);
 
    end
 end
 
-%% Create graphic of spatial distribution of 'bad' observations & their QC value.
+%% Create graphic of spatial distribution of 'flagged' observations & their QC value.
 %
 % 0     observation assimilated
 % 1     observation evaluated only
@@ -124,39 +167,42 @@
    '''outlier rejected''',...
    '''reserved for future use'''};
 
-if (obsstruct.numbadqc > 0 ) % if there are bad observation to plot ... carry on.
+if (obsstruct.numflagged > 0 ) % if there are flagged observation to plot ... carry on.
 
-   figure(gcf+1); clf
+   if (twoup <= 0)
+      figure(gcf+1); clf
+   end
    
-   subplot('position',[0.1 0.20 0.8 0.65])
+   subplot('position',positions(2,:))
    
-   zmin = min(obsstruct.badobs.z);
-   zmax = max(obsstruct.badobs.z);
+   zmin = min(flaggedobs.z);
+   zmax = max(flaggedobs.z);
 
-   pstruct.scalearray = 128 * ones(size(obsstruct.badobs.obs));
+   prej = 100.0 * length(flaggedobs.obs) / ...
+         (length(flaggedobs.obs) + length(obsstruct.obs));
+   pstruct.scalearray = 128 * ones(size(flaggedobs.obs));
    pstruct.colorbarstring = QCString;
-   pstruct.clim = [min(obsstruct.badobs.qc) max(obsstruct.badobs.qc)];
+   pstruct.clim = [min(flaggedobs.qc) max(flaggedobs.qc)];
    pstruct.str1 = sprintf('%s level (%.2f - %.2f)',obsstruct.ObsTypeString,zmin,zmax);
-   pstruct.str2 = sprintf('%s (%d bad observations)',  ...
-                                    obsstruct.CopyString, ...
-                             length(obsstruct.badobs.obs));
+   pstruct.str2 = sprintf('%s (%d ''good'', %d ''flagged'' -- %.2f %%)', obsstruct.CopyString, ...
+                      length(obsstruct.obs), length(flaggedobs.obs), prej);
  
-   obsstruct.badobs.obs = obsstruct.badobs.qc;  % plot QC values, not obs values
+   flaggedobs.obs = flaggedobs.qc;  % plot QC values, not obs values
    if ( zmin ~= zmax )
 
       pstruct.axis = [xmin xmax ymin ymax zmin zmax];
 
-      plot_3D(obsstruct.badobs, pstruct)
+      plot_3D(flaggedobs, pstruct);
 
    else
 
       pstruct.axis = [xmin xmax ymin ymax];
 
-      plot_2D(obsstruct.badobs, pstruct)
+      plot_2D(flaggedobs, pstruct);
 
    end
    
-   subplot('position',[0.1 0.05 0.8 0.10])
+   subplot('position',positions(3,:))
    axis off
 
    %% If the QC is a DART QC, we know how to interpret them.
@@ -164,15 +210,16 @@
    switch lower(strtrim(QCString))
       case 'dart quality control',
 
-         qcvals  = unique(obsstruct.badobs.qc); 
+         qcvals  = unique(flaggedobs.qc); 
          qccount = zeros(size(qcvals));
+         s = cell(length(qcvals));
          for i = 1:length(qcvals)
-            qccount(i) = sum(obsstruct.badobs.qc == qcvals(i));
+            qccount(i) = sum(flaggedobs.qc == qcvals(i));
             s{i} = sprintf('%d obs with qc == %d %s',qccount(i),qcvals(i), ...
                    dartqc_strings{qcvals(i)});
          end
    
-         dy =  1.0/length(s);
+         dy =  0.8*1.0/length(s);
          for i = 1:length(s)
             text(0.0, (i-1)*dy ,s{i})
          end
@@ -213,10 +260,10 @@
 % We need to determine the geographic subset of the elevation matrix.
 %---------------------------------------------------------------------------
 
-lon_ind1 = min(find(ax(1) <= lons));
-lon_ind2 = min(find(ax(2) <= lons));
-lat_ind1 = min(find(ax(3) <= lats));
-lat_ind2 = min(find(ax(4) <= lats));
+lon_ind1 = find(ax(1) <= lons, 1);
+lon_ind2 = find(ax(2) <= lons, 1);
+lat_ind1 = find(ax(3) <= lats, 1);
+lat_ind2 = find(ax(4) <= lats, 1);
 
 if (isempty(lon_ind1)), lon_ind1 = 1;    end;
 if (isempty(lon_ind2)), lon_ind2 = nlon; end;
@@ -273,7 +320,7 @@
 
 
 
-function plot_3D(obsstruct, pstruct)
+function h1 = plot_3D(obsstruct, pstruct)
 
 if (pstruct.clim(1) == pstruct.clim(2))
    % If all the observations have the same value, setting the
@@ -282,7 +329,7 @@
    % colormap and setting the colorbar to have some more
    % colors 'on top' - that are never used.
    cmap = colormap;
-   h = plot3(obsstruct.lons, obsstruct.lats, obsstruct.z, 'bo');
+   h = plot3(obsstruct.lons, obsstruct.lats, obsstruct.z, 'bd');
    set(h,'MarkerFaceColor',cmap(1,:),'MarkerEdgeColor',cmap(1,:))
    set(gca,'Clim',[pstruct.clim(1) pstruct.clim(2)+1])
    set(gca,'XGrid','on','YGrid','on','ZGrid','on')
@@ -291,12 +338,12 @@
    scatter3(obsstruct.lons, obsstruct.lats, obsstruct.z, ...
          pstruct.scalearray, obsstruct.obs, 'd', 'filled');
 end
+h1   = gca;
+clim = get(h1,'CLim');
 
-clim = get(gca,'CLim');
-
 axis(pstruct.axis)
 
-title( {pstruct.str1, pstruct.str3, pstruct.str2}, 'Interpreter','none','FontSize',16);
+title( {pstruct.str1, pstruct.str3, pstruct.str2}, 'Interpreter','none','FontSize',14);
 xlabel('longitude')
 ylabel('latitude')
 
@@ -315,19 +362,19 @@
 
 myworldmap;
 set(gca,'CLim',clim)
-h = colorbar;
-set(get(h,'YLabel'),'String',pstruct.colorbarstring,'Interpreter','none')
+hb = colorbar;
+set(get(hb,'YLabel'),'String',pstruct.colorbarstring,'Interpreter','none')
 
 
 
 
-function plot_2D(obsstruct, pstruct)
+function h1 = plot_2D(obsstruct, pstruct)
 
 axis(pstruct.axis); hold on; worldmap('light');
 
 if (pstruct.clim(1) == pstruct.clim(2))
    cmap = colormap;
-   h = plot(obsstruct.lons, obsstruct.lats, 'bo');
+   h = plot(obsstruct.lons, obsstruct.lats, 'bd');
    set(h,'MarkerFaceColor',cmap(1,:),'MarkerEdgeColor',cmap(1,:))
    set(gca,'Clim',[pstruct.clim(1) pstruct.clim(2)+1])
    set(gca,'XGrid','on','YGrid','on')
@@ -338,9 +385,10 @@
          pstruct.scalearray, obsstruct.obs, 'd', 'filled');
 end
 
-clim = get(gca,'CLim');
+h1   = gca;
+clim = get(h1,'CLim');
 
-title( {pstruct.str1, pstruct.str3, pstruct.str2}, 'Interpreter','none','FontSize',16);
+title( {pstruct.str1, pstruct.str3, pstruct.str2}, 'Interpreter','none','FontSize',14);
 xlabel('longitude')
 ylabel('latitude')
 

Modified: DART/trunk/diagnostics/matlab/plot_obs_netcdf_diffs.m
===================================================================
--- DART/trunk/diagnostics/matlab/plot_obs_netcdf_diffs.m	2010-02-03 18:02:11 UTC (rev 4250)
+++ DART/trunk/diagnostics/matlab/plot_obs_netcdf_diffs.m	2010-02-03 20:50:30 UTC (rev 4251)
@@ -1,17 +1,55 @@
 function obsstruct = plot_obs_netcdf_diffs(fname, ObsTypeString, region,  ...
-                      CopyString1, CopyString2, QCString, maxQC, verbose)
+                      CopyString1, CopyString2, QCString, maxQC, verbose, twoup)
+% plot_obs_netcdf_diffs will plot the difference between any two 'copies' of an observation-style netcdf file.
 %
+% bob = plot_obs_netcdf_diffs(fname, ObsTypeString, region, CopyString1, CopyString2, ...
+%                             QCString, maxQC, verbose, twoup);
+%
+% fname			the name of the netCDF file (from obs_seq_to_netcdf)
+%
+% ObsTypeString		the variable of interest (from ObsTypesMetaData variable) 
+%
+% region		region of interest [lonmin lonmax latmin latmax zmin zmax]
+%
+% CopyString1		the difference is taken 'CopyString2 - CopyString1'
+% CopyString2
+%
+% QCString		There are multiple QC copies 
+% maxQC			The highest QC value of interest. Anything more than this
+%			will not be differenced. The locations will be plotted on
+%			a separate axis.
+% verbose		logical flag ... if 'true', a table listing the possible 
+%			observation types and observation counts is displayed.
+%
+% twoup			logical flag indicating that both the plot of the rejected 
+%			observations and the plot of the differences is 
+%			created on the same figure window.
+%
+% The 'copies' are recorded in the netCDF 'CopyMetaData' variable - 
+% the observation types are recorded in the 'ObsTypesMetaData' variable, 
+% and the QC strings of interest are recorded in QCMetaData - so
+% ncdump -v CopyMetaData,ObsTypesMetaData,QCMetaData obs_sequence_001.nc
+% is a useful endeavor.
+%
+% $Id$
+%
+%--------------------------------------------------
+% EXAMPLE : plot the difference between the ensemble mean of the prior 
+% and the actual observation value - while rejecting any obs that had
+% a DART QC greater than 3 ( prior forward operator failed ... or worse) 
+%--------------------------------------------------
 % fname         = 'obs_sequence_001.nc';
 % ObsTypeString = 'RADIOSONDE_U_WIND_COMPONENT';
 % region        = [0 360 -90 90 -Inf Inf];
 % CopyString1   = 'NCEP BUFR observation';
 % CopyString2   = 'prior ensemble mean';
 % QCString      = 'DART quality control';
-% maxQC         = 1;
+% maxQC         = 1;   % max QC to consider when taking differences.
 % verbose       = 1;   % anything > 0 == 'true'
+% twoup         = 1;   % anything > 0 == 'true'
 %
 % bob = plot_obs_netcdf_diffs(fname, ObsTypeString, region, CopyString1, CopyString2, ...
-%                       QCString, maxQC, verbose);
+%                             QCString, maxQC, verbose, twoup);
 
 % record the user input
 
@@ -21,127 +59,57 @@
 %
 % <next few lines under version control, do not edit>
 % $URL$
-% $Id$
 % $Revision$
 % $Date$
 
-obsstruct.fname         = fname;
-obsstruct.ObsTypeString = ObsTypeString;
-obsstruct.region        = region;
-obsstruct.CopyString1   = CopyString1;
-obsstruct.CopyString2   = CopyString2;
-obsstruct.QCString      = QCString;
-obsstruct.maxQC         = maxQC;
-obsstruct.verbose       = verbose;
-
-% get going
-
-ObsTypes       = nc_varget(fname,'ObsTypes');
-ObsTypeStrings = nc_varget(fname,'ObsTypesMetaData');
-CopyStrings    = nc_varget(fname,'CopyMetaData');
-QCStrings      = nc_varget(fname,'QCMetaData');
-
-t              = nc_varget(fname,'time');
-obs_type       = nc_varget(fname,'obs_type');
-z_type         = nc_varget(fname,'which_vert');
-
-loc            = nc_varget(fname,'location');
-obs            = nc_varget(fname,'observations');
-qc             = nc_varget(fname,'qc');
-
-my_types   = unique(obs_type);  % only ones in the file, actually.
-timeunits  = nc_attget(fname,'time','units');
-timerange  = nc_attget(fname,'time','valid_range');
-calendar   = nc_attget(fname,'time','calendar');
-timebase   = sscanf(timeunits,'%*s%*s%d%*c%d%*c%d'); % YYYY MM DD
-timeorigin = datenum(timebase(1),timebase(2),timebase(3));
-timestring = datestr(timerange + timeorigin);
-
-% Echo summary if requested
-
-if ( verbose > 0 ) 
-   for i = 1:length(my_types)
-      obtype = my_types(i);
-      inds   = find(obs_type == obtype);
-      myz    = loc(inds,3);
-     
-      disp(sprintf('N = %6d %s obs (type %3d) between levels %.2f and %.2f', ...
-               length(inds), ObsTypeStrings(obtype,:), obtype, ...
-               unique(min(myz)), unique(max(myz))))
-   end
-
-%  uniquelevels = unique(loc(:,3));
-
-%  for i = 1:length(uniquelevels)
-%     mylevel = uniquelevels(i);
-%     inds    = find(loc(:,3) == mylevel);
-%     disp(sprintf('level %2d %f has %d observations',i,mylevel,length(inds)))
-%  end
-
+if (exist(fname,'file') ~= 2)
+   error('%s does not exist.',fname)
 end
 
-% Find observations of the correct types.
-
-myind     = strmatch(ObsTypeString,ObsTypeStrings);
-
-if ( isempty(myind) )           
-   error('no %s observations ... stopping',obsstruct.ObsTypeString)
-end
-
-mytype1   = get_copy_index(fname, CopyString1);
-mytype2   = get_copy_index(fname, CopyString2);
-inds      = find(obs_type == myind);
-mylocs    = loc(inds,:);
-myobs1    = obs(inds,mytype1);
-myobs2    = obs(inds,mytype2);
-myobs     = myobs2 - myobs1;
-
-if ~ isempty(QCString)
-   myQCind = get_qc_index(fname,  QCString);
-   myqc    = qc(inds,myQCind);
+if ( twoup > 0 ) 
+   clf; orient tall
+   positions = [0.1, 0.55, 0.8, 0.35 ; ...
+                0.1, 0.10, 0.8, 0.35 ; ...
+                0.1, 0.02, 0.8, 0.08];
 else
-   myqc    = [];
+   clf; orient landscape
+   positions = [0.1, 0.20, 0.8, 0.65 ; ...
+                0.1, 0.20, 0.8, 0.65 ; ...
+                0.1, 0.05, 0.8, 0.10];
 end
 
-clear myobs1 myobs2 obs loc qc
+%% Read the observation sequence
 
-% geographic subset if needed
+obsstruct  = read_obs_netcdf(fname, ObsTypeString, region, ...
+                    CopyString1, QCString, verbose);
 
-inds = locations_in_region(mylocs,region);
+obsstruct2 = read_obs_netcdf(fname, ObsTypeString, region, ...
+                    CopyString2, QCString, verbose);
 
-obsstruct.lons = mylocs(inds,1);
-obsstruct.lats = mylocs(inds,2);
-obsstruct.z    = mylocs(inds,3);
-obsstruct.obs  =  myobs(inds);
-obsstruct.Ztyp = z_type(inds);
-obsstruct.numbadqc = 0;
+xdat = obsstruct2.obs - obsstruct.obs;
+obsstruct.obs = xdat;
+clear obsstruct2 xdat
 
-if (isempty(myqc))
-   obsstruct.qc = [];
-else
-   obsstruct.qc = myqc(inds);
-end
-
 % subset based on qc value
 
-if ( (~ isempty(myqc)) & (~ isempty(maxQC)) )
+if ( (~ isempty(obsstruct.qc)) && (~ isempty(maxQC)) )
 
    inds = find(obsstruct.qc > maxQC);
 
-   obsstruct.numbadqc = length(inds);
-   
+   obsstruct.numflagged = length(inds);
+
    if (~isempty(inds))
-       badobs.lons = obsstruct.lons(inds);
-       badobs.lats = obsstruct.lats(inds);
-       badobs.Ztyp = obsstruct.Ztyp(inds);
-       badobs.z    = obsstruct.z(   inds);
-       badobs.obs  = obsstruct.obs(inds);
-       badobs.qc   = obsstruct.qc(inds);       
+       flaggedobs.lons = obsstruct.lons(inds);
+       flaggedobs.lats = obsstruct.lats(inds);
+       flaggedobs.Ztyp = obsstruct.Ztyp(inds);
+       flaggedobs.z    = obsstruct.z(   inds);
+       flaggedobs.obs  = obsstruct.obs( inds);
+       flaggedobs.qc   = obsstruct.qc(  inds);
    end
-   
-   disp(sprintf('Removing %d obs with a %s value greater than %f', ...
-                length(inds),QCString,maxQC))
 
+   fprintf('Removing %d obs with a %s value greater than %f\n', ...
+                length(inds),QCString,maxQC)
+
    inds = find(obsstruct.qc <= maxQC);
 
    bob = obsstruct.lons(inds); obsstruct.lons = bob;
@@ -153,12 +121,9 @@
 
 end
 
-%-------------------------------------------------------------------------------
-% Create graphic with area-weighted symbols for the good observations.
-%-------------------------------------------------------------------------------
+%% Create graphic with area-weighted symbols for the good observations.
+%  It has happened that there have been zero good observations in a file.
 
-figure(1); clf
-
 xmin = min(region(1:2));
 xmax = max(region(1:2));
 ymin = min(region(3:4));
@@ -166,110 +131,145 @@
 zmin = min(obsstruct.z);
 zmax = max(obsstruct.z);
 
-scalearray = scaleme(obsstruct.obs,36);
-scalearray = 128 * ones(size(obsstruct.obs));
+pstruct.colorbarstring = sprintf('%s - %s',CopyString2,CopyString1);
+pstruct.region = region;
+pstruct.str3   = sprintf('%s - %s',obsstruct.timestring(1,:),obsstruct.timestring(2,:));
 
-scatter3(obsstruct.lons, obsstruct.lats, obsstruct.z, ...
-              scalearray, obsstruct.obs,'d','filled');
+if ( length(obsstruct.obs) < 1 ) 
+   fprintf('There are no ''good'' observations to plot\n')
+else
 
-axis([xmin xmax ymin ymax zmin zmax])
+   subplot('position',positions(1,:))
 
-str1 = sprintf('%s level (%.2f - %.2f)',ObsTypeString,zmin,zmax);
-str2 = sprintf('%s - %s (%d locations)',CopyString2,CopyString1,length(obsstruct.obs));
-str3 = sprintf('%s - %s',timestring(1,:),timestring(2,:));
+   % choose a symbol size based on the number of obs to plot.
 
-title( {str1, str3, str2}, 'Interpreter','none','FontSize',16);
-xlabel('longitude')
-ylabel('latitude')
+   if (length(obsstruct.obs) > 1000) 
+      pstruct.scalearray = scaleme(obsstruct.obs, 36);
+   else
+      pstruct.scalearray = 128.0 * ones(size(obsstruct.obs));
+   end
+   pstruct.clim   = [min(obsstruct.obs) max(obsstruct.obs)];
+   pstruct.str2   = sprintf('%s (%d locations)',obsstruct.CopyString,length(obsstruct.obs));
 
-if     (obsstruct.Ztyp(1) == -2) % VERTISUNDEF     = -2
-   zlabel('curious ... undefined')
-elseif (obsstruct.Ztyp(1) == -1) % VERTISSURFACE   = -1
-   zlabel('surface')
-elseif (obsstruct.Ztyp(1) ==  1) % VERTISLEVEL     =  1
-   zlabel('level')
-elseif (obsstruct.Ztyp(1) ==  2) % VERTISPRESSURE  =  2
-   set(gca,'ZDir','reverse')
-   zlabel('pressure')
-elseif (obsstruct.Ztyp(1) ==  3) % VERTISHEIGHT    =  3
-   zlabel('height')
+   % If all the observations live on the same level ... make a 2D plot.
+
+   if ( zmin ~= zmax )
+
+      pstruct.axis = [xmin xmax ymin ymax zmin zmax];
+      pstruct.str1 = sprintf('%s level (%.2f - %.2f)',obsstruct.ObsTypeString,zmin,zmax);
+
+      plot_3D(obsstruct, pstruct);
+
+   else
+
+      pstruct.axis = [xmin xmax ymin ymax];
+      pstruct.str1 = sprintf('%s',obsstruct.ObsTypeString);
+
+      plot_2D(obsstruct, pstruct);
+
+   end
 end
 
-myworldmap;
-set(gca,'CLim',[min(obsstruct.obs) max(obsstruct.obs)])
-h = colorbar;
-set(get(h,'YLabel'),'String',ObsTypeString,'Interpreter','none')
+%% Create graphic of spatial distribution of 'flagged' observations & their QC value.
+%
+% 0     observation assimilated
+% 1     observation evaluated only
+%   --- everything above this means the prior and posterior are OK
+% 2     assimilated, but the posterior forward operator failed
+% 3     Evaluated only, but the posterior forward operator failed
+%   --- everything above this means only the prior is OK
+% 4     prior forward operator failed
+% 5     not used
+% 6     prior QC rejected
+% 7     outlier rejected
 
-%-------------------------------------------------------------------------------
-% Create graphic of spatial distribution of 'bad' observations & their QC value.
-%-------------------------------------------------------------------------------
+dartqc_strings = { ...
+   '''observation evaluated only''', ...
+   '''assimilated, but the posterior forward operator failed''', ...
+   '''evaluated only, but the posterior forward operator failed''',...
+   '''prior forward operator failed''',...
+   '''not used''',...
+   '''prior QC rejected''',...
+   '''outlier rejected''',...
+   '''reserved for future use'''};
 
-if (obsstruct.numbadqc > 0 )
+if (obsstruct.numflagged > 0 ) % if there are flagged observation to plot ... carry on.
 
-   figure(2); clf
+   if (twoup <= 0)
+      figure(gcf+1); clf
+   end
    
-   subplot('position',[0.1 0.20 0.8 0.65])
-   scalearray = 128 * ones(size(badobs.obs));
+   subplot('position',positions(2,:))
    
-   zmin = min(badobs.z);
-   zmax = max(badobs.z);
-   
-   scatter3(badobs.lons, badobs.lats, badobs.z, scalearray, badobs.qc,'filled')
-   
-   title( {str1, str3, 'Bad Observations'}, 'Interpreter','none','FontSize',16);
-   xlabel('longitude')
-   ylabel('latitude')
-   
-   if     (badobs.Ztyp(1) == -2) % VERTISUNDEF     = -2
-      zlabel('curious ... undefined')
-   elseif (badobs.Ztyp(1) == -1) % VERTISSURFACE   = -1
-      zlabel('surface')
-   elseif (badobs.Ztyp(1) ==  1) % VERTISLEVEL     =  1
-      zlabel('level')
-   elseif (badobs.Ztyp(1) ==  2) % VERTISPRESSURE  =  2
-      set(gca,'ZDir','reverse')
-      zlabel('pressure')
-   elseif (badobs.Ztyp(1) ==  3) % VERTISHEIGHT    =  3
-      zlabel('height')
+   zmin = min(flaggedobs.z);
+   zmax = max(flaggedobs.z);
+
+   prej = 100.0 * length(flaggedobs.obs) / ...
+         (length(flaggedobs.obs) + length(obsstruct.obs));
+   pstruct.scalearray = 128 * ones(size(flaggedobs.obs));
+   pstruct.colorbarstring = QCString;
+   pstruct.clim = [min(flaggedobs.qc) max(flaggedobs.qc)];
+   pstruct.str1 = sprintf('%s level (%.2f - %.2f)',obsstruct.ObsTypeString,zmin,zmax);
+   pstruct.str2 = sprintf('%s (%d ''good'', %d ''flagged'' -- %.2f %%)', obsstruct.CopyString, ...
+                      length(obsstruct.obs), length(flaggedobs.obs), prej);
+ 
+   flaggedobs.obs = flaggedobs.qc;  % plot QC values, not obs values
+   if ( zmin ~= zmax )
+
+      pstruct.axis = [xmin xmax ymin ymax zmin zmax];
+
+      plot_3D(flaggedobs, pstruct);
+
+   else
+
+      pstruct.axis = [xmin xmax ymin ymax];
+
+      plot_2D(flaggedobs, pstruct);
+
    end
    
-   axis([region(1) region(2) ymin ymax zmin zmax])
-   
-   myworldmap;
-   set(gca,'CLim',[min(badobs.qc) max(badobs.qc)])
-   h = colorbar;
-   set(get(h,'YLabel'),'String',QCString,'Interpreter','none')
-   
-   subplot('position',[0.1 0.05 0.8 0.10])
+   subplot('position',positions(3,:))
    axis off
+
+   %% If the QC is a DART QC, we know how to interpret them.
+
+   switch lower(strtrim(QCString))
+      case 'dart quality control',
+
+         qcvals  = unique(flaggedobs.qc); 
+         qccount = zeros(size(qcvals));
+         for i = 1:length(qcvals)
+            qccount(i) = sum(flaggedobs.qc == qcvals(i));
+            s{i} = sprintf('%d obs with qc == %d %s',qccount(i),qcvals(i), ...
+                   dartqc_strings{qcvals(i)});
+         end
    
-   qcvals  = unique(badobs.qc);
-   qccount = zeros(size(qcvals));
-   for i = 1:length(qcvals)
-      qccount(i) = sum(badobs.qc == qcvals(i));
-      s{i} = sprintf('%d obs with qc == %d',qccount(i),qcvals(i));
+         dy =  0.8*1.0/length(s);
+         for i = 1:length(s)
+            text(0.0, (i-1)*dy ,s{i})
+         end
+
+      otherwise,
+         str = sprintf('no way to interpret values of %s',strtrim(QCString));
+         text(0.0, 0.0, str)
    end
-   
-   dy = 1.0/length(s);
-   for i = 1:length(s)
-      text(0.0, (i-1)*dy ,s{i})
-   end
-
 end
 
+
+
 function h = myworldmap
 
-%---------------------------------------------------------------------------
+%%--------------------------------------------------------------------------
 % GET THE ELEVATION DATA AND SET UP THE ASSOCIATED COORDINATE DATA
 %---------------------------------------------------------------------------
 
-load topo;                 % GET Matlab-native [180x360] ELEVATION DATASET
-lats = [-89.5:89.5];       % CREATE LAT ARRAY FOR TOPO MATRIX
-lons = [0.5:359.5];        % CREATE LON ARRAY FOR TOPO MATRIX
+load topo;               % GET Matlab-native [180x360] ELEVATION DATASET
+lats = -89.5:89.5;       % CREATE LAT ARRAY FOR TOPO MATRIX
+lons = 0.5:359.5;        % CREATE LON ARRAY FOR TOPO MATRIX
 nlon = length(lons);
 nlat = length(lats);
 
-%---------------------------------------------------------------------------
+%%--------------------------------------------------------------------------
 % IF WE NEED TO SWAP HEMISPHERES, DO SO NOW.
 % If we didn't explicitly tell it, make a guess.
 %---------------------------------------------------------------------------
@@ -281,28 +281,28 @@
    topo = [ topo(:,nlon/2+1:nlon) topo(:,1:nlon/2) ];
 end
 
-%---------------------------------------------------------------------------
+%%--------------------------------------------------------------------------
 % We need to determine the geographic subset of the elevation matrix.
 %---------------------------------------------------------------------------
 
-lon_ind1 = min(find(ax(1) <= lons));
-lon_ind2 = min(find(ax(2) <= lons));
-lat_ind1 = min(find(ax(3) <= lats));
-lat_ind2 = min(find(ax(4) <= lats));
+lon_ind1 = find(ax(1) <= lons, 1);
+lon_ind2 = find(ax(2) <= lons, 1);
+lat_ind1 = find(ax(3) <= lats, 1);
+lat_ind2 = find(ax(4) <= lats, 1);
 
-if (isempty(lon_ind1)) lon_ind1 = 1;    end;
-if (isempty(lon_ind2)) lon_ind2 = nlon; end;
-if (isempty(lat_ind1)) lat_ind1 = 1;    end;
-if (isempty(lat_ind2)) lat_ind2 = nlat; end;
+if (isempty(lon_ind1)), lon_ind1 = 1;    end;
+if (isempty(lon_ind2)), lon_ind2 = nlon; end;
+if (isempty(lat_ind1)), lat_ind1 = 1;    end;
+if (isempty(lat_ind2)), lat_ind2 = nlat; end;
 
 elev = topo(lat_ind1:lat_ind2,lon_ind1:lon_ind2);
 x    = lons(lon_ind1:lon_ind2);
 y    = lats(lat_ind1:lat_ind2);
 
-%---------------------------------------------------------------------------
+%%--------------------------------------------------------------------------
 % Contour the "subset"
 % There are differences between 6.5 and 7.0 that make changing the colors
-% of the filled contours a real pain. Providing both solutions.
+% of the filled contours a real pain.
 %---------------------------------------------------------------------------
 
 orgholdstate = ishold;
@@ -319,19 +319,19 @@
 
 [c,h] = contourf(x,y,elev,[0.0 0.0],'k-');
 
-new_level = 1000;
+h_patch   = get(h, 'Children');
 
-h_patch = get(h, 'Children');
-
 for i = 1:numel(h_patch)
     y = get(h_patch(i), 'YData');
     s = size(y);
     set(h_patch(i), 'ZData', zlevel*ones(s),'FaceColor',fcolor);
 end
 
-if (orgholdstate == 0) hold off; end;
+if (orgholdstate == 0), hold off; end;
 
 
+
+
 function s = scaleme(x,minsize)
 % scaleme returns a uniformly scaled array the same size as the input
 % array where the maximum is 10 times the minimum 
@@ -343,3 +343,81 @@
 
 s = x*slope + b;
 
+
+
+function h1 = plot_3D(obsstruct, pstruct)
+
+if (pstruct.clim(1) == pstruct.clim(2))
+   % If all the observations have the same value, setting the
+   % colorbar limits is a real pain. Fundamentally, I am 
+   % forcing the plot symbols to be the lowest color of the
+   % colormap and setting the colorbar to have some more
+   % colors 'on top' - that are never used.
+   cmap = colormap;
+   h = plot3(obsstruct.lons, obsstruct.lats, obsstruct.z, 'bd');
+   set(h,'MarkerFaceColor',cmap(1,:),'MarkerEdgeColor',cmap(1,:))
+   set(gca,'Clim',[pstruct.clim(1) pstruct.clim(2)+1])
+   set(gca,'XGrid','on','YGrid','on','ZGrid','on')
+
+else
+   scatter3(obsstruct.lons, obsstruct.lats, obsstruct.z, ...
+         pstruct.scalearray, obsstruct.obs, 'd', 'filled');
+end
+h1   = gca;
+clim = get(h1,'CLim');
+
+axis(pstruct.axis)
+
+title( {pstruct.str1, pstruct.str3, pstruct.str2}, 'Interpreter','none','FontSize',14);
+xlabel('longitude')
+ylabel('latitude')
+
+if     (obsstruct.Ztyp(1) == -2) % VERTISUNDEF     = -2
+   zlabel('unspecified')
+elseif (obsstruct.Ztyp(1) == -1) % VERTISSURFACE   = -1
+   zlabel('surface')
+elseif (obsstruct.Ztyp(1) ==  1) % VERTISLEVEL     =  1
+   zlabel('level')
+elseif (obsstruct.Ztyp(1) ==  2) % VERTISPRESSURE  =  2
+   set(gca,'ZDir','reverse')
+   zlabel('pressure')
+elseif (obsstruct.Ztyp(1) ==  3) % VERTISHEIGHT    =  3
+   zlabel('height')
+end
+
+myworldmap;
+set(gca,'CLim',clim)
+hb = colorbar;
+set(get(hb,'YLabel'),'String',pstruct.colorbarstring,'Interpreter','none')
+
+
+
+
+function h1 = plot_2D(obsstruct, pstruct)
+
+axis(pstruct.axis); hold on; worldmap('light');
+
+if (pstruct.clim(1) == pstruct.clim(2))
+   cmap = colormap;
+   h = plot(obsstruct.lons, obsstruct.lats, 'bd');
+   set(h,'MarkerFaceColor',cmap(1,:),'MarkerEdgeColor',cmap(1,:))
+   set(gca,'Clim',[pstruct.clim(1) pstruct.clim(2)+1])
+   set(gca,'XGrid','on','YGrid','on')
+
+else
+
+   scatter(obsstruct.lons, obsstruct.lats, ...
+         pstruct.scalearray, obsstruct.obs, 'd', 'filled');
+end
+
+h1   = gca;
+clim = get(h1,'CLim');
+
+title( {pstruct.str1, pstruct.str3, pstruct.str2}, 'Interpreter','none','FontSize',14);
+xlabel('longitude')
+ylabel('latitude')
+
+set(gca,'CLim',clim)
+h = colorbar;
+set(get(h,'YLabel'),'String',pstruct.colorbarstring,'Interpreter','none')
+hold off

Modified: DART/trunk/diagnostics/matlab/read_obs_netcdf.m
===================================================================
--- DART/trunk/diagnostics/matlab/read_obs_netcdf.m	2010-02-03 18:02:11 UTC (rev 4250)
+++ DART/trunk/diagnostics/matlab/read_obs_netcdf.m	2010-02-03 20:50:30 UTC (rev 4251)
@@ -1,5 +1,5 @@
 function obsstruct = read_obs_netcdf(fname, ObsTypeString, region, CopyString, ...
-                                     QCString, maxQC, verbose)
+                                     QCString, verbose)
 %% read_obs_netcdf reads in the netcdf flavor observation sequence file
 %                  and returns a subsetted structure.
 %
@@ -8,10 +8,9 @@
 % region        = [0 360 -90 90 -Inf Inf];
 % CopyString    = 'NCEP BUFR observation';
 % QCString      = 'DART quality control';
-% maxQC         = 2;

@@ Diff output truncated at 40000 characters. @@


More information about the Dart-dev mailing list