Tim Hoar's Matlab Demo
February 2012

Info about Tim Hoar

You can contact me at 303-497-1708 or by emailing thoar 'at' ucar 'dot' edu
If you are at NCAR, my extension is simply 1708.

My demo is intended to provide enough information to make you curious and perhaps get something done, but it is by no means exhaustive.

Info about Matlab

Matlab is an interpreted language that handles matrices with a natural syntax. This generally means a very short spin-up period for people unfamiliar with Matlab. One of Matlab's founding fathers (who is still president of the MathWorks) is Cleve Moler of Linpack fame.

As with any interpreted language, it is possible to write some incredibly slow F77 code. We recommend against that ... Take advantage of the vector- or matrix- based syntax and avoid loops whenever possible.

Table of Contents:

  1. Preparing your environment
  2. Starting Matlab
  3. Help
  4. Syntax
  5. Public Tools
  6. Import ascii data, make a scatterplot
  7. Handle Graphics
  8. Make a contour plot
  9. Meridional/Zonal averages
  10. Linear Least Squares
  11. Masking
  12. Masked Contour Plot
  13. Cheap Projections
  14. Scripts
  15. Functions
  16. Profiling
  17. Printing
  18. Importing binary files
  19. netCDF
  20. Mapping/Projections
  21. movies/animations

Matlab is gradually getting more JAVA-dependent, and the GUI interface is getting to be horribly slow to launch. It has some nice features that make it worthwhile if you are going to be using Matlab for 'a while', but for short sessions I find the launch time unacceptably long. Furthermore, I 'grew up' on the command line, so I'd just as soon use it for most purposes. For me, the motivation to use the GUI is the debugger. Another cool thing is the XML help ... put an "info.xml" file in a directory in the MATLABPATH and the directory is added to the help widget -- now called the "launchpad" ...



The (unix/linux/mac) Environment for Matlab:

Nothing is really required, but there are some things that make life nicer, naturally.

mkdir ~/matlab
mkdir ~/matlab/data/

Matlab automatically searches for a ~/matlab directory upon startup, this is a nice place to have general purpose scripts/functions. If there exists a ~/matlab/startup.m file, it is automatically executed upon startup. The file may contain any sequence of valid Matlab commands. If there are directories that contain certain third-party toolboxes, the obvious way to add them is with your startup.m file, which could be as simple as this:

%% Startup.m  is executed by the matlabrc script automatically at startup.
% append this directory to your MATLABPATH
%
addpath('~/matlab/data');


To start Matlab:

Simply type matlab & at the UNIX prompt or click on the Matlab icon if you're a person who likes that sort of thing. If your (unix) PATH is correct, this will work. Windows and Mac users may have a little Matlab icon on the desktop/dock ... that works too, naturally. You can fire up Matlab from any directory and your MATLABPATH will be set to search the normal Matlab installation, anything specified in your ~/matlab/startup.m file, and the current working directory (which, for the icon startups, is a bit obfuscated).

The matlab prompt is:

>>
if you didn't get the little splash screen, it means your DISPLAY is not set properly, which will make graphics a challenge. Let me know ASAP.

To quit Matlab:

>> quit

I like to actually quit the application from the Command Window prompt as opposed to just clicking on some button ... I've saved myself more than once from prematurely ending a session. You get into that button-clicking mode and and Doh! ... I meant to minimize, not kill!


Matlab Help

There are lots of ways to get help in Matlab. Simply typing help at the command line gets you started. If you know the command you want, (for example "fft") simply type help fft.

If you do not know the name of the command, you can look for functions by keywords -- lookfor fft, for example. This works for ALL functions in the MATLABPATH, including the ones you create. More on this when we get into the function section, ditto for "help".

If you are running with the JAVA interface, Matlab also has an interactive WWW-based help system, called HelpDesk. This is the 800# gorilla of help. Search all the manuals, connect to the MathWorks FAQ site, list by topics, alphabetically, etc. helpdesk fires up the GUI.

The Mathworks (the parent company) has online resources, too. The home page for Matlab is
http://www.mathworks.com and has links to a Getting Started page with tons of examples, etc. You should definitely wander around this site for a while to get acquainted with it.


Matlab's syntax:

Matlab is short for Matrix Laboratory. If you can think of the algebra in 2D, it will probably work exactly as you expect. The thing to get used to is that any command without a ";" at the end will print the result of the command to the screen. Not particularly desirable for large results. I am in the habit of terminating every command with a ";", whether it needs one or not.

General help for all the relational operators can be had with help relops. The only tricky part is that the square brackets are used for defining arrays, parentheses are for indexing, and the variables MUST be conformable.

Example

a = [0:127];                            % "a" is a row vector
b = cos(2*pi*a/length(a));              % so is "b"
plot(b(1:64));                          % only plot the first 64 elements
title('My mental retention prowess.');
xlabel('(minutes)');
ylabel('fraction of capacity');

Conformable?

For example, multiplying a 10x3 matrix by a 10x3 matrix will generate an error message, unless you want the operator to work on an element-by-element basis. Here is another example of trying to multiply a 1xN matrix by another 1xN matrix ... simply not possible ...

size(a)
size(b)
a*b
For example, if you want to multiply each element of an array by the corresponding element of another array:
c = a.*b;           % should be reminiscent of the "dot product"
size(c)
d = sum(c);         % wow

c = a'*b;           % transpose a to make it 128-x-1 * 1-x-128 -> 128-x-128
size(c)

Thinking like vectors and matrices

It is best to simply ignore the existence of vectors and just admit they are really N x 1 or 1 x N matrices. All the rules of matrix algebra apply. Some functions are tailored for 1D matrices and can be used on higher-dimensional matrices, like sum.

c = b'*b;           % premultiplying b by its transpose -> 128-x-128
d = sum(c)          % what is "d"? (semicolon intentionally left off)
imagesc(c);         % color-code the result and plot
colorbar;           % plot a legend
title('Not Quite Psychedelic')
xlabel('X index')
ylabel('Y index')

The classic one is fft. Taking the fft of a 1D variable is pretty clear. What happens if you feed fft a M x N matrix? Matlab grew from Fortran beginnings, so it takes ffts of each column, since these are stored sequentially in memory (and it can take unit strides). If you want a real 2D fft, use fft2. This is a common theme in Matlab. Operations that have a different connotation for 2D as opposed to 1D have an additional "2" in the function name.

load topo;
wow = topo - mean(topo(:));
C = fft(wow);      % take the fft of each column of "c"
whos               % "who and size" (semicolon intentionally left off)
D = fft2(wow);
subplot(2,2,1)
  imagesc(real(C))
  title('Real part of FFT of each column')
  colorbar
subplot(2,2,2)
  imagesc(fftshift(real(D)))
  title('Real part of 2DFFT')
  colorbar
subplot(2,2,3)
  imagesc(imag(C))
  title('Imaginary part of FFT of each column')
  colorbar
subplot(2,2,4)
  imagesc(fftshift(imag(D)))
  title('Imaginary part of 2DFFT')
  colorbar


Public-domain functions/tools:

SEA-MAT is a free collection of toolboxes for Matlab. There is a distinct Oceanographic flavor to it. Download these into your favorite directory (Don't forget to include the directory in your MATLABPATH -- preferably by tailoring your ~/matlab/startup.m file).

There are simply hundreds of third-party books and toolboxes. Check out the MathWorks home page and poke around.


Import an ascii file (of a matrix):

The ascii file in question contains ONLY numeric characters, no alphabetic. This is important if you want to use the (simple) load command. If you have mixed characters, you want to see the help file for fread.

first, we copy the ascii file to ~/matlab/data/soi.ascii and get on with it. The matlab variable will be the filename without the extension, so we should wind up with a variable called soi.

load soi.ascii
whos;			% the command you will use most
soi(1,:)                % see the contents of the first row, all columns ... UGLY
format bank
soi(1,:)                % for this variable, a more intuitive view
soi(1,2:13)             % Tim - talk about storage modes, precision.
years = soi(:,1);	% save years as Nx1 matrix
a = soi(:,2:13);        % strip out years, other columns are monthly values.
inds = find(a < -90);	% locate the "missing" values
a(inds) = NaN;		% replace with Matlab's "missing" flag.
[nrows,ncols] = size(a);       
b = reshape(a',nrows*ncols,1);	% reformat into Nx1 matrix.
plot(b)				% plot, but pretty ugly

%
% Lets zoom in on just the first 10 years (120 months)
%

axis([0 10*12 -Inf Inf])	% [xmin xmax ymin ymax]  (Inf == unknown)
grid

%
% It would be convenient to have a better time axis.
% I will make a matrix the same size as the input with each entry
% corresponding to the month midpoint == year.fraction
%

t    = ones(nrows,1) * [0.5/12 : 1/12 : 11.5/12];   % matrix of fractions
tmat = years * ones(1,ncols) + t;		    % matrix of times
T    = reshape(tmat',nrows*ncols,1);                % array of times

plot(T,b)


Handle Graphics:

Perhaps the best part of Matlab. Infinitely customizable graphics.

You will definitely want wysiwyg.m in your ~/matlab directory.


% A pretty ugly figure

h1 = subplot('position',[0.2 0.4 0.4 0.2]);	% l, b, w, h
     plot(1:10)
     xlabel('wow')
     ylabel('unbelievable!')
h2 = subplot('position',[0.1 0.1 0.8 0.2]);
     plot(11:20)
     xlabel('m/s^2')
     ylabel('t_i')
h3 = subplot('position',[0.2 0.6 0.6 0.3]);
     imagesc(peaks)
     title('trumpets blare, twice')
     h = colorbar;

orient tall		% fill a page -- portrait style
wysiwyg			% What You See Is What You Get ... wysiwyg

% Clean it up. 

get(h)
set(h,'Position',[0.743 0.6 0.025 0.3]);	% thinner colorbar
child = get(h,'Ylabel');			% get handle to the Ylabel.
set(child,'String','meters/furlong')

get(h3)
set(h3,'YTick',[1 13 22 38]);			% change tick positions
set(h3,'YTickLabel',['     1';'    13';'kahuna';'    38']); % change labels
child = get(h3,'Title')
set(child,'String',{'Trumpets Blare','Two times'},'FontSize',18)

get(h1)
set(h1,'Position',[0.2 0.4 0.6 0.1], ...
       'YAxisLocation','right');           % line continuation, multiple
                                           % attributes in one "set"


Contour Plots:

The only thing tricky about contour plots in matlab is the resulting orientation. (1,1) is at the bottom left.

clear			% clears all variables in your workspace!!!!!
load topo		% a default dataset
whos
contour(topo)
colorbar

Changing the number of contour lines is easy.

contour(topo,5)
colorbar

Specifying which contour levels is also easy.

contour(topo,[0:500:4500])
colorbar

Personally, I like the imageplots a lot better, they give clues as to the original resolution. However, the plot has (1,1) in the upper left.

imagesc(topo)
colorbar
This is the introduction to "Handle Graphics". It is generally trivial to tweak almost any aspect of a figure.
imagesc(topo)
set(gca,'YDir','normal')	% GetCurrentAxis attribute "YDir"; set to ...
colorbar
To see _what_ you can tweak, do a:
get(gca)
There are other neat plots, like mesh, pcolor, spy and a bunch more.


Meridional/Zonal means:

We need a field of data. The peaks functions creates some. In Matlab, output variables are on the left of the equal sign. If there are more than one, they must be enclosed in square brackets []. If you only put a single variable on the left, the FIRST output variable is returned, the rest are ignored.
[x,y,z] = peaks(360);		% CREATE SOME FAKE DATA (z is 360x360)
imagesc(z);			% TAKE A QUICK LOOK AT THE DATA
imagesc scales a matrix so the min corresponds to the lowest color and the max corresponds the highest. Any of the "image" commands plots element 1,1 in the upper left hand corner. This can be changed by setting the appropriate axis attribute. This is "advanced", but simple.
newz = z(1:2:360,:);		% GRAB EVERY OTHER ROW OF DATA
imagesc(newz);			% IMAGE THE SUBSETTED MATRIX
set(gca,'YDir','normal');	% PLOT 1,1 IN THE LOWER LEFT
Taking the mean is simple. In general, Matlab applies operators to each column, there is no need to "loop" over them. Since we conceptualize our matrix z as 180 latitudes X 360 longitudes, we get the meridional or zonal means in the following fashion:
clf;				% CLEAR OUT THE FIGURE WINDOW (GOOD STYLE)
subplot(2,2,1);			% CHOP PLOT WINDOW INTO A 2X2 MATRIX
imagesc(newz);			% CHEAP PLOT OF DATA
set(gca,'YDir','normal');	% PLOT 1,1 IN THE LOWER LEFT
title('Peak data');

subplot(2,2,4);			% use the 4th window of the 2x2 
contour(newz);			% duhhhhhhhh
title('Contoured peak data');

subplot(2,2,3);			% USE THE THIRD WINDOW OF THE 2x2 set
mmeans = mean(newz);		% CREATE MEANS OF EACH COLUMN (ALL LATITUDES)
plot(mmeans);			% PLOT THEM (versus their index [1,360])
title('Meridional means');

subplot(2,2,2);
zmeans = mean(newz');		% TRANSPOSE THE MATRIX AND FIND THE MEANS
plot(zmeans);			% PLOT THEM (versus their index [1,180]
title('Zonal means');

Labelled contour plots

[cs,h] = contour(peaks); 	% this is kinda sneaky
clabel(cs,h,'fontsize',15,'color','r','rotation',0)

Weighted Averages

This is simply multiplying two arrays together. Since Matlab does "matrix" multiplication by default, it is necessary to have a separate "operator" for this -- enter the dot "." -- which means to do a the operation "pairwise". Since arrays are actually either Mx1 or 1xM matrices, you must make sure the two matrices in question have the same dimension.
clf;				% CLEAR OUT THE FIGURE WINDOW (GOOD STYLE)
t = 0.5:1:179.5;                % Just making a digital frequency for 'sin' 
a = sin(2*pi*t/(2*length(t)));  % create half a sinusoid.
w = a.^2;	                % CREATE WEIGHTING FUNCTION (column vector)
c = w.*zmeans;			% CREATE THE WEIGHTED AVERAGE
lats = [-89:1:90];		% CREATE A "REALISTIC" LATITUDE AXIS
plot(lats,zmeans,'-.',lats,c,'-');
grid;				% PUTS A GRID ON THE AXIS
legend('unweighted zonal mean','weighted zonal mean')
Here's where you click/drag the legend (multiple times if you wish). Instead of plot, try semilogy, semilogx, or loglog.


Linear Least Squares:

The solution to A*X = B is simply X = A\B; Pretty boring, but true.

help \
or
help relop


Masking (a bunch of color-coded matrix elements):

Masking can be achieved by setting the desired matrix elements equal to some predefined color (like the background color).

Just for grins, put continents.m in your ~/matlab directory.

clear; clf;				% clear workspace, clear figure
load topo;				% get some elevation data [180x360]
lon = [0.5:359.5];
lat = [-89.5:89.5];

a   = peaks(360);			% make some bogus data (too big)
cph = a(1:2:360,:);			% cph is same size as elevation data

mask = topo < 0;			% make a land/sea mask (sea is 1.0)

clear a topolegend topomap1 topomap2;		% for illustrative purposes

figure(1); clf;                         % make figure 1 'active' and clear the figure
subplot(3,1,1);                         % subset plot into 3 rows, 1 column, draw in #1
imagesc(lon,lat,topo);                  % use lon,lat arrays for X,Y
title('Global topography')
set(gca,'YDir','normal');               % put -90,0 in the lower left.
axis(gca,'image');                      % make 'deltax' == 'deltay'
xlabel('Longitude (degrees E)')        
ylabel('Latitude (degrees N)')
h = colorbar;                           % draw a scalebar and give me the handle
set(get(h,'YLabel'),'String','meters')  % set some annotation on the scalebar

subplot(3,1,2);                         % use the second subplot region
imagesc(lon,lat,mask);                  % plot up the land/ocean mask
set(gca,'YDir','normal');
title('0 == land, 1 == ocean')
colorbar;
colormap(jet);

subplot(3,1,3);                         % use the third subplot region
imagesc(lon,lat,cph);
set(gca,'YDir','normal');
colorbar;

figure; 			       % GET ANOTHER GRAPHICS WINDOW
newdat = cph.*mask;	               % Use only "cph" data over land
imagesc(lon,lat,newdat,[-7 7]);	       % quick look 
set(gca,'YDir','normal');	       % correct orientation
title('"Peaks" Masked by the Earth''s topography.');
colorbar;			       % because I said so
tim = jet;			       % snag a colormap
tim(32:33,:) = 0.9;		       % make colors around 0 == gray
colormap(tim);			       % apply new colormap

continents


Masked Contour Plots:

Just for grins, put sinusoid.m in your ~/matlab directory.

figure(1); clf
a   = sinusoid(360,1,1,90);             % make some phony data
b   = a*a';
c   = b(1:2:360,:)*10;
lon = [0.5:359.5];
lat = [-89.5:89.5];

subplot(2,1,1)
imagesc(lon,lat,c);                     % look at the phony data
set(gca,'YDir','normal');               % correct orientation

% MASK OUT THE "LAND"
inds  = find(mask > 0);                 % Find locations of land
c(inds)  = NaN;                         % set land elements to NAN

subplot(2,1,2)
contour(lon,lat,c,[-10:2:10]);          % "gapped" contours
hold on;                                % add to current plot
[d,h] = contour(lon,lat,topo,[0 0]);    % continents


Cheap Projections:

For this, we can "texture map" (drape?) a matrix over a matched set of 3 matrices specifying a "solid".
clf;
load topo
[x,y,z] = sphere(35);					% MAKE A 3D SURFACE
h = surface(x,y,z,'FaceColor','texture','Cdata',topo)	% DO TEXTURE MAP,
							% KEEP GRAPHICS HANDLE
set(h,'EdgeColor','none')				% USE HANDLE TO CHANGE
							% AN ATTRIBUTE
axis square;						% MAKE AXES EQUAL
axis off;						% TURN OFF LABELLING
colormap(jet);						% A DIFFERENT PALETTE

Also try the free mapping routines in the SEA-MAT distribution.


Scripts:

By now, you should be sick of cutting and pasting. Enter the script, generically called a ".m" file. By inserting your matlab commands into a file called (for example) foo.m, you can simply type "foo" at the Matlab prompt and the entire file is checked for syntax and executed. Put the following lines in a file called ~/matlab/foo.m:

% This is a generic matlab script.
%

  load topo;                            % GET [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
  imagesc(lons,lats,topo);              % CREATE SOME PLOT w/ true x,y limits
  set(gca,'YDir','normal');             % CORRECT ORIENTATION
 
  worldmap; 

Then, (one at a time) from Matlab's command line:

which foo
help foo
type foo
foo
Notice that the initial block of comment lines forms the "help" entry for the script! Pretty cool. A nice way to keep documentation up-to-date with the program.


Functions:

A Matlab Function is a special .m file. The first line of the file is the function declaration.

You can peruse most functions with type.

The FIRST line of the help file should contain some keywords. This is the only line searched by the lookfor function.

copy and paste this into a text file in your ~/matlab directory. Call the file ... Imagesc.m ... or bob.m

function h = Imagesc(x,y,datmat)
% Imagesc is the same as imagesc except the YDir is normal.

% Brilliantly devised and executed by Tim. 1 Jan 1601

h = imagesc(x,y,datmat);
set(h,'YDir','normal')

From the Matlab command line,

help Imagesc

Tinker with the help line, screw up the syntax, call it with the wrong number of arguments ... knock yourself out.


Profiling:

profile your favorite script/function --- VERY impressive. follow the example from "help profile"





Importing binary:

Easy, as long as you know how the data is written. For this exercise, save some binary data as ~/matlab/data/chi_jan96.ieee

With a clever combination of fread, I feel supremely confident in the ability to read any valid file. Read the help file for fread and fopen

Fortran unformatted binary

Every Fortran unformatted write makes a "record" that has a 4 byte header and a 4 byte tailer(?) as well as the data you want to write. C does not do this, this is the biggest difference in the binaries. To be able to read both is a trivial thing IF you remember the little 4 byte extras.

The binary file below was written in the following manner:

      real datmat(129,64)
      integer nt

      do i = 1,nt
            ...
         write(iunit)datmat
      enddo
so each record is (1+129*64+1)*4 bytes, the file is this_same_number x nt. Logically the format is:
[4bytes][129*64*4 bytes of data][4bytes]
[4bytes][129*64*4 bytes of data][4bytes]
           ...
[4bytes][129*64*4 bytes of data][4bytes]
[4bytes][129*64*4 bytes of data][4bytes]
The following segment just reads the data and makes a crude contour plot. For more information on contour plots -- try help contour or help clabel. Since each plot is being made in a loop, Matlab must be told to `pause' so we can look at each plot being made. Otherwise, Matlab's graphics is intelligent enough to realize it shouldn't bother to draw each frame (on the screen) since you couldn't possibly just want to see it flicker by.
nlon = 129;
nlat = 64;
nt   = 5;

fid  = fopen('~/matlab/data/chi_jan96.ieee','r')
frewind(fid);
 
for islice = 1:nt,
 
      expr = sprintf('slice %.0f',islice);
 
      dum1 = fread(fid, 1,'float32');
      udat = fread(fid,[nlon nlat],'float32');
      dum1 = fread(fid, 1,'float32');

      contour(udat);
      title(expr);
      disp('Hit a key to continue ...'); pause;

end

Fortran direct access

Basically exactly the same as the unformatted binary without the little 4 byte record headers/enders. Every record is constrained to be the same, however. The logical format is:

[xxx bytes of data]
[xxx bytes of data]
        ...
[xxx bytes of data]
[xxx bytes of data]
Your Matlab script to read it could be:
fid  = fopen('~/matlab/data/DirectAccess.ieee','r')
frewind(fid);
for islice = 1:nt,
      udat = fread(fid,[xxx],'float32');
end

C binary

The most flexible yet. "Let the buyer beware". C binary generally comes with no header bytes, everything is simply data pasted together. If you get off by a byte, you get garbage. There is no error-checking. You can mix reads of different lengths and data types in any fashion. The following is snytactically correct, but may not match the data at all.

fid  = fopen('~/matlab/data/wildcard.ieee','r')

udat = fread(fid,[10],'float32');
a    = fread(fid,[10 30],'int32');
b    = fread(fid,[1],'float64');


Printing:

You can print from the plot GUI directly, which I have never done. I got into the game before that was possible and never saw the need ... I do all my printing from the command line.

To a particular printer:

If you leave off the -P[printer] argument, the default printer is used.

To a file:

Making Matlab do the rasterization

Lots of postscript files are simply ascii files of postscript commands. You can view and change the source with your favorite editor. This shifts the burden of rendering the figure from the computer to the printer. There can be some relatively small postscript files that take an extremely long time to print because of this. By making the computer render the figures to some finite raster density, the computational burden stays on the computer at the expense of making potentially large (but simple and relatively fast to print) postscript files for the printer. This is particularly true for maps.

If you have figures that are taking too long to print, you may consider having Matlab do the rendering. There is a huge tradeoff between size of the file and the raster level (dots per inch).

print -dpsc2 -zbuffer -r200 [filename]


NetCDF

[overview] [reading] [writing] [examples]

Matlab and netCDF:

At long last (about 15 years late) Matlab finally natively supports
NetCDF (Network Common Data Form) files. Prior to Matlab V 2008b, a free third-party package was required to read/write netCDF files. Despite having 15 to 20 years' worth of functions that use the third-party package, I am not going to show you how to use them. The remaining examples are being reworked to use the native Matlab commands. From the Matlab prompt, type:
help netcdf

Reading a (known) variable from an existing netCDF file

First, get
example.nc, STN_050258.nc, and Daily_b06_45.nc. In example.nc, the variable is Elevation and is a 2-dimensional array. It could just as easily be a scalar or an "N"-dimensional variable.

ncid  = netcdf.open('example.nc','NC_NOWRITE');    % create an ID to the netcdf file. 
netcdf.inq(ncid)
varid = netcdf.inqVarID(ncid, 'EW');               % determines the ID of the variable of interest.
EW    = netcdf.getVar(ncid, varid);                % actually gets the variable.
SN    = netcdf.getVar(ncid, netcdf.inqVarID(ncid,'SN'));
x     = netcdf.getVar(ncid, netcdf.inqVarID(ncid,'Elevation'),'double');
size(x)
Imagesc(EW,SN,x);
title('Dr. Evil''s Volcano Lair','FontSize',18)

Creating a netCDF file.

The strategy here is that Matlab is almost a direct translation of the C interface to netCDF. Check out the netCDF C documentation from UNIDATA for the overall strategy of working with netCDF and then the Matlab interface will seem pretty obvious.

%% make some data that we want to save in the netCDF file
clear
load topo
lat = -89.5:1:89.5;
lon = 0.5:1:359.5;
Imagesc(lon,lat,topo);

%% Create the empty template of the file.
%  This includes scalars declaring the dimensions,
%  global attributes for the file,
%  the coordinate variables ...  

ncid     = netcdf.create('TimTopo.nc', 'NC_NOCLOBBER');
LonDimID = netcdf.defDim(ncid, 'lon', length(lon));
LatDimID = netcdf.defDim(ncid, 'lat', length(lat));

% Get and use the handle to the file so we can set some global attributes
VarID    = netcdf.getConstant('NC_GLOBAL');
netcdf.putAtt(ncid, VarID, 'Filename', 'TimTopo.nc');
netcdf.putAtt(ncid, VarID, 'CreationDate', date);
netcdf.putAtt(ncid, VarID, 'PersonToBlame', 'Tim');

% define some variables that will be useful.
VarIdLat = netcdf.defVar(ncid, 'Lat' , 'NC_FLOAT', LatDimID);
VarIdLon = netcdf.defVar(ncid, 'Lon' , 'NC_FLOAT', LonDimID);
VarID    = netcdf.defVar(ncid, 'topo', 'NC_FLOAT', [LonDimID LatDimID]);

netcdf.endDef(ncid)  % Leave define mode ... important.

%% Actually put the values in the predefined slots.

netcdf.putVar(ncid, VarIdLat  ,lat );
netcdf.putVar(ncid, VarIdLon  ,lon );
netcdf.putVar(ncid, VarID     ,topo)

% Make sure everyone is done, and close the file. Finis.
netcdf.sync(ncid)
netcdf.close(ncid)

Now, check the data with the unix utility 'ncdump', Matlab, NCL, Python, Perl, C++

Reading a hyperslab of a variable instead of the WHOLE variable.

netCDF files can be HUGE ... too big to simply read into memory ... This is where you want to read just a "slab" of data. By way of explanation, lets do this on a variable we CAN read into memory, and again using just the hyperslabbing.
ncid  = netcdf.open('/fs/image/home/thoar/public_html/Prior_Diag.nc','NC_NOWRITE');
netcdf.inq(ncid)
lonmat  = netcdf.getVar(ncid, netcdf.inqVarID(ncid,'XLONG_d01'));
latmat  = netcdf.getVar(ncid, netcdf.inqVarID(ncid,'XLAT_d01'));
times   = netcdf.getVar(ncid, netcdf.inqVarID(ncid,'time'));
copy    = netcdf.getVar(ncid, netcdf.inqVarID(ncid,'copy'));
varid   = netcdf.inqVarID(ncid,'T2_d01');

% Read in the whole variable at once:

temps   = netcdf.getVar(ncid, varid,'double');

size(temps)

% temps is a 4D variable: 221-x-127-x-3-x-4

datmat = temps(:,:,1,2);

clf;
h = pcolor(lonmat, latmat, datmat);
set(h,'LineStyle','none');

title('Hunh?')
h2 = colorbar('vert');
set(get(h2,'YLabel'),'String','degrees')

disp('What''s going on? the matrix is being plotted ''correctly''')
disp('but there is one element that is in the wrong hemisphere.')
disp('The longitudes in lonmat are [-180,180] so the wraparound')
disp('point is problematic. Just change the longitudes to be ')
disp('[0,360] by finding those elements that are less than zero')
disp('and adding 360 to them.\n')
disp('Pausing, hit any key to continue ...')
pause

inds = find(lonmat < 0.0);
lonmat(inds) = lonmat(inds) + 360.0;

h = pcolor(lonmat, latmat, datmat);
set(h,'LineStyle','none');

title('Ta DA','Interpreter','none')
h2 = colorbar('vert');
set(get(h2,'YLabel'),'String','degrees')

disp('Let''s only read in a 2D slab of data')
disp('Pausing, hit any key to continue ...')
pause

% For simplicity, we are exploting the fact that we KNOW the size/shape of the variable.
% If you do not, the best way is to use netcdf.inqVar and then loop over
% al the varDimIDs to find their size.
% [varname, xtype, varDimIDs, varAtts] = netcdf.inqVar(ncid,varid) 
%
% remember that the Matlab netCDF routines are implemented with the C-style addressing,
% so the first element is zero, not one. The rest of Matlab, as far as I can tell,
% has always started counting at one ... so the break from their own standard is disturbing
% and annoying.

start = [  0,  0,0,1];
count = [221,127,1,1];
bob   = netcdf.getVar(ncid, varid, start, count, 'double');
size(bob)

clf
subplot(3,1,1)

   h = pcolor(lonmat, latmat, datmat);
   set(h,'LineStyle','none');
   title('Whole Variable at Once')
   h2 = colorbar('vert');
   set(get(h2,'YLabel'),'String','degrees')

subplot(3,1,2)

   h = pcolor(lonmat, latmat, bob);
   set(h,'LineStyle','none');
   title('Just a 2D hyperslab')
   h2 = colorbar('vert');
   set(get(h2,'YLabel'),'String','degrees')

subplot(3,1,3)

   h = pcolor(lonmat, latmat, (datmat-bob) );
   set(h,'LineStyle','none');
   title('Difference')
   h2 = colorbar('vert');
   set(get(h2,'YLabel'),'String','degrees')


Mapping/Projections
[overview] [documentation] [reading] [creating] [examples]

Mapping / Projections

I will use the mapping toolbox as a demonstation of how to explore a topic and write your own matlab function. We can also use some of the matlab GUI tools, so let's log out of matlab and start it up WITH java enable ... i.e. the default way. Also, get the MyMap.m function.

help map
help mapdemos

Movies/Animations [overview] [documentation] [reading] [creating] [examples]

Movies / Animations

I used to use the matlab getframe, movie commands ... but then I moved to a Mac and realized that for really nice animations, i just needed to dump each frame to a .png file and make the animation in QuickTime.

Movie Documentation

some user

Ingesting animations

Creating a movie.

There are two functions called MPGWRITE and MPGREAD for creating MPEG files on the UNIX and PC platforms. MPGWRITE translates a Matlab movie into an MPEG file. MPGREAD translates a movie file in MPEG format into a Matlab movie matrix. You can download them from the anonymous FTP server:
ftp://ftp.mathworks.com/pub/contrib/v5/graphics/mpgwrite
ftp://ftp.mathworks.com/pub/contrib/v5/graphics/mpgread

Low Level Examples


Tim Hoar thoar 'at' ucar 'dot' edu