matlabio - a MATLAB MAT-file reader/writer

Doug Stein (doug@wri.com)
Wolfram Research, Inc.
16 February 1994

Installation

The MathLink template program matlabio reads and writes MATLAB MAT-files. Here's how to install it.

matlabio = Install["matlabio"]

Here are the names it defines. They exist in their own package context called MATLABIO.

Names["MATLABIO`*"]

Here are the usage messages for the four functions.

?MATLABMatrixNames

?MATLABQ

?MATLABReadMatrix

?MATLABWriteMatrix

Example: Reading and modifying MATLAB's "Penny"

Read the Penny data

First, let's see what matrices are in the file. MAT-files allow multiple matrices in a file, so MATLABMatrixNames effectively gives the "table of contents" of the MAT-file.

MATLABMatrixNames["penny.mat"]

It seems that the data is descriptively named "P". I have to reverse the data since the MAT-file has Lincoln upside down. The MATLAB folks take care of this by setting a funny plotting option; we can handle this by reversing the data.

penny = Reverse[MATLABReadMatrix["penny.mat", "P"]];

Dimensions[penny]

Plotting the Penny

Here are three obvious visualizations using this data:

ListDensityPlot[penny, Mesh->False];

ListContourPlot[penny];

The ListPlot3D hasn't been computed here since it generates lots of PostScript and would make this notebook rather large. You can generate it if you want.....

ListPlot3D[penny, Mesh->False];

Coloring the Penny (Optional)

Now we'll color the penny the same way as the MATLAB folks. Their formula is:
	c = min(1,gray(m)*diag([1.2500 0.7812 0.4975]));
Ours would be:

CopperColor[val_] := RGBColor[
						Min[1, 1.25 val],
						0.7812 val,
						0.4975 val
					]

Note: ColorFunction->CopperColor looks good only at 16 or 24-bit color (Thousands or Millions in Macintosh lingo). If running at less colors, omit this ColorFunction option to get a grey-scale image. Macintosh users can also choose "Colors..." from the File menu and pick "Dither patterns" for the dialog item entitled "When rendering bitmap images (DensityPlots), use:"

ListDensityPlot[penny, Mesh->False,
	ColorFunction->CopperColor];

ListPlot3D[penny, Mesh->False,
	ColorFunction->CopperColor];

ListContourPlot[penny,
	ColorFunction->CopperColor];

Modifying the Penny

Let's severely muddle the penny data by taking a modified Fourier transform. I follow a suggestion developed in the book Applied Mathematica by Shaw and Tigg on page 412. centeredFourier[] shifts the low-frequency components into the center of the picture and shifts the high-frequency components to the periphery.

centeredFourier[x_List] := Transpose[RotateRight[
	Transpose[RotateRight[Fourier[x], 64]], 64]];

pennyFourier = centeredFourier[penny];

ListDensityPlot[Abs[pennyFourier], Mesh->False];

Writing the Modified Data

Let's write to a MAT-file (PennyFourier.mat) and name as a MATLAB matrix (PennyFourier) the Mathematica matrix (pennyFourier). Got it?

MATLABWriteMatrix["PennyFourier.mat", "PennyFourier",
	pennyFourier]

Extending matlabio - advanced uses

Writing a list of matrices into a single file

If you want to write a list of matrices to a MAT-file from Mathematica , simply Map the writing function over the list of matrices. The variable matnum is used to give distinct names to the matrices (otherwise the MATLAB file writing library used by matlabio will overwrite rather than append matrices).

writeAllMatrices[filename_String, matrices_] :=
	Module[{fname = filename, matnum = 1},
		Map[MATLABWriteMatrix[fname,
				"mat"<>ToString[matnum++], #]&,
			matrices];
		fname
	]

Example

Let's make a list of three matrices.

matList = {
	Table[Sin[x y],{x,0,Pi,Pi/10},{y,0,Pi,Pi/10}],
	Table[Random[],{15},{15}],
	Table[Mod[x,y],{x,1,10},{y,1,10}]
	};

Checking the dimensions of the matrices...

Map[Dimensions, matList]

Now writing them...

writeAllMatrices["TripleThreat.mat", matList]

Reading all the matrices in a file

If you want to read all the matrices in a MAT-file into a Mathematica list, simply Map the reading function over the list of matrix names.

readAllMatrices[filename_String] :=
	Module[{fname = filename},
		Map[MATLABReadMatrix[fname, #]&,
			MATLABMatrixNames[fname]]
	]

Example

Let's read the matrices we just wrote...

newMatList = readAllMatrices["TripleThreat.mat"];

...and for fun, let's make a ListDensityPlot of each. I'm using DisplayFunction->Identity since I want to combine the plots into one graphic.

plots = Map[
	ListDensityPlot[#, DisplayFunction->Identity]&,
	newMatList
]

Now that I have the plots I'll combine them into one GraphicsArray.

Show[GraphicsArray[plots]]

Error Handling and Shutting Down

matlabio functions emit Mathematica warning messages if something goes wrong. They then return $Failed.

MATLABMatrixNames["foobar.mat"]

matlabio will properly quit when the Mathematica kernel quits. Nothing special needs to be done. If, however, you wish to manually quit matlabio without quitting Mathematica, simply evaluate:

Uninstall[matlabio]

How to build matlabio

Macintosh - MPW

Assuming MATLAB and MathLink  libraries are installed as per instructions, the following rebuilds matlabio using MPW:

Note: replace "::Extern:Scripts:cmex" with the location of the cmex script supplied by the MATLAB folks.

mprep -Application matlabio.tm -o matlabio.tm.c
::Extern:Scripts:cmex -libmat matlabio.c matlabio.tm.c {Libraries}MathLink881.o
Rez -append "{RIncludes}"mathlink.r -o matlabio

Unix

This is a little tricky since both Mathematica and MATLAB supply scripts to automate the build process of MathLink programs and MEX/LIBMAT programs respectively. Unfortunately, these scripts are oblivious to each other. The basic idea is to "mprep" the matlabio.tm file into C code (matlabio.tm.c). One then compiles matlabio.tm.c and matlabio.c into object code and links the two files with libML.a and whatever the MATLAB library is. Here's a quick and dirty way of automating as much as possible...

Step 1 - Use mprep to preprocess matlabio.tm into matlabio.tm.c

mprep -o matlabio.tm.c matlabio.tm

Step 2 - Use cmex to build matlabio

cmex -O -Iinclude_path -Llibrary_path -lML matlabio.tm.c matlabio.c -o matlabio
   (where include_path is the location of mathlink.h and library_path
    is the location of libML.a)

Windows

Follow the extensive directions in the MathLink for Windows Developer's Kit (MLDK). Again, you first use mprep to preprocess matlabio.tm into mlabiotm.c.

\mathlink\bin\mprep matlabio.tm -o mlabiotm.c

Using the command line suggested in the MLDK, compile and link mlabiotm.c, matlabio.c, and the MathLink and MATLAB libraries. Remember to add the directory containing the MATLAB include files to your search path. Also remember to add the appropriate LIBMAT library.