1.3. Matlab IO

Sourcery VSIPL++'s vsip_csl library has routines that can read and write views from Matlab formated text and binary files.

1.3.1. Matlab Text (.m) Files

The Matlab_text_formatter object writes a view to an output stream in Matlab text file format (Matlab text files commonly have an .m suffix).

The following example illustrates using the Matlab_text_formatter to write a matrix and a vector to the same file.

The first part of the example shows the necessary includes and declarations. In addition to any VSIPL++ headers necessary for your program (the example includes headers for vectors, matrices, and generation functions), it is also necessary to include the vsip_csl/matlab_text_formatter.hpp header file. The example also uses the vsip and vsip_csl namespaces for convenience.

#include <iostream>
#include <fstream>

#include <vsip/initfin.hpp>
#include <vsip/vector.hpp>
#include <vsip/matrix.hpp>
#include <vsip/selgen.hpp>
#include <vsip/map.hpp>

#include <vsip_csl/matlab_text_formatter.hpp>

using namespace vsip;
using namespace vsip_csl;

The second part of the example shows writing a file. First matrix m and view v are created and filled with ramp data. Then an output file stream out is created. Finally, Matlab_text_formatter is used to write the views.

  // Initialize matrix 'm'.
  Matrix<float> m(3, 3);
  for(index_type i=0;i<3;i++)
    m.row(i) = ramp<float>(3*i, 1, 3);

  // Initialize vector 'v'.
  Vector<float> v(3);
  v = ramp<float>(0, 1, 3);

  // Open output stream to file 'temp.m'.
  std::ofstream out("text.m");

  // Write 'm' and 'a' to output stream
  out << Matlab_text_formatter<Matrix<float> >(m, "m");
  out << Matlab_text_formatter<Vector<float> >(v, "v");

The output file temp.m contains the following

m = 
[
  [ 0 1 2 ]
  [ 3 4 5 ]
  [ 6 7 8 ]
];
v = 
[ 0 1 2 ];

This text file can be run inside of a Matlab console window to load matrix a and vector v.

1.3.2. Matlab Binary Files (.mat)

The Matlab_bin_formatter object can read and write views to a streams in Matlab binary file format (Matlab binary files commonly have a .mat suffix). For reading matlab binary files, the iterator interface described in the next section may be more convenient.

1.3.2.1. Writing a Matlab Binary Format File

Writing matlab binary format files is similar to writing text format files, except that a header must be written to the file with Matlab_bin_header before writing each view with Matlab_binary_formatter. The following example shows how to write a matrix and a vector to a .mat file.

The first part of the example shows the necessary includes and declarations. In addition to any VSIPL++ headers necessary for your program (the example includes headers for vectors, matrices, and generation functions), it is also necessary to include the vsip_csl/matlab_bin_formatter.hpp header file. The example also uses the vsip and vsip_csl namespaces for convenience.

#include <iostream>
#include <fstream>

#include <vsip/initfin.hpp>
#include <vsip/vector.hpp>
#include <vsip/matrix.hpp>
#include <vsip/selgen.hpp>
#include <vsip/map.hpp>

#include <vsip_csl/matlab_bin_formatter.hpp>

using namespace vsip;
using namespace vsip_csl;

The second part of the example shows writing a file. First matrix m and view v are created and filled with ramp data. Then an output file stream out is created. Finally, Matlab_text_formatter is used to write the views.

  // Initialize matrix 'm'.
  Matrix<float> m(3, 3);
  for(index_type i=0;i<3;i++)
    m.row(i) = ramp<float>(3*i, 1, 3);

  // Initialize vector 'v'.
  Vector<float> v(3);
  v = ramp<float>(0, 1, 3);

  // Open output stream to file 'sample.mat'.
  std::ofstream out("sample.mat");

  // Write matlab binary format header.  This must is done once at the
  // beginning of the file before any views can be written.
  out << Matlab_bin_hdr("example");
  
  // Write 'm' and 'v' to output stream
  out << Matlab_bin_formatter<Matrix<float> >(m, "m");
  out << Matlab_bin_formatter<Vector<float> >(v, "v");

This result file sample.mat can be read by Matlab, or other programs capable of reading matlab binary format files, such as Octave and Sourcery VSIPL++ applications.

1.3.2.2. Reading a Matlab Binary Format File

Reading a matlab binary format file is similar to writing one. After the file is opened, it is necessary to read the file header. This header is used by each of the subsequent reads. The following example shows how to read the views back from the sample.mat file written in the previous example.

The same includes are used for this example.

First matrix m and view v are created. Their size must match the size of the views in the matlab binary file. Next an input stream is created to read the binary data. The header is read first into a Matlab_bin_header. Finally each view is read, using Matlab_bin_formatter objects.

  // Create matrix and vector views of correct size.
  Matrix<float> m(3, 3);
  Vector<float> v(3);
    
  // Open an input stream to read sample.mat.
  std::ifstream in("sample.mat");

  // Read matlab binary format file header.  This must be done once
  // after the file is opened before reading any views.  The header is
  // then used by Matlab_bin_formatter to determine global file
  // parameters such as endianness, etc.
  Matlab_bin_hdr h;
  in >> h;

  // Read the views.
  in >> Matlab_bin_formatter<Matrix<float> >(m, "m", h);
  in >> Matlab_bin_formatter<Vector<float> >(v, "v", h);

Note that when using Matlab_bin_formatter the size and types of the VSIPL++ views m and v must match the size and type of the views stored in the binary file. If they do not match, an exception will be thrown. In situations were the size and type are not known in advance, it may be more convenient to use the Matlab iterator interface, described in the next section.

1.3.3. Matlab_file iterator interface

In situations where the size, type, and order of views written in a matlab file is not known in advance, the Matlab_file interface should be used to read the file. Matlab_file provides an iterator interface to step through each view in a file. The size, type, and name of each view can be queried before it is read. This allows an appropriate VSIPL++ view to be constructed dynamically.

The Matlab_file object handles opening and reading a file. It provides a standard iterator interface with begin and end functions.

Matlab_file::iterators correspond to views in the file. Dereferencing the iterator returns a Matlab_view_header object. This contains information about the view, including its name, type, dimensionality, and size.

The read_view function reads the view referred to by the iterator.

The following example shows how to read the m matrix from the sample.mat binary file used in the previous examples.

The first part of the example shows the necessary includes and declarations. The Matlab_file interface is contained in the vsip_csl/matlab_file.hpp header file.

        #include <iostream>
#include <fstream>

#include <vsip/initfin.hpp>
#include <vsip/vector.hpp>
#include <vsip/matrix.hpp>
#include <vsip/selgen.hpp>
#include <vsip/map.hpp>

#include <vsip_csl/matlab_file.hpp>

using namespace vsip;
using namespace vsip_csl;

      

The second part of the example shows how to read the file. First the Matlab_file object mf is created. Then iterators begin and end are created to iterate over the views stored in the file. For each view, the name and size are checked to determine if it should be read. Finally, read_view is used to read the selected view.

          // Create Matlab_file object for 'sample.mat' file.
  Matlab_file mf("sample.mat");
  Matlab_file::iterator cur = mf.begin();
  Matlab_file::iterator end = mf.end();
  Matlab_view_header* vhdr;

  // Block pointer to hold the matrix.  The block will be allocated
  // once it's size is known.
  Dense<2, float>* m_block = NULL;

  // Iterate through views in file.
  while (cur != end)
  {
    vhdr = *cur;

    // Check if view is the one we're looking for.
    if(!strcmp(vhdr->array_name, "m") && vhdr->num_dims == 2)
    {
      // Check for multiple views named "m" in file.
      assert(m_block == NULL);

      // Create block and view.
      // At this point we can make the block size match size in the file.
      m_block = new Dense<2, float>(Domain<2>(vhdr->dims[0], vhdr->dims[1]));
      Matrix<float> tmp(*m_block);

      // Read view from file.
      mf.read_view(tmp, cur);
    }

    ++cur; // Move to next view stored in the file.
  }

  // Check that we found a view named "a" in file.
  assert(m_block != NULL);

  // Create a view to process "m".
  Matrix<float> m(*m_block);

      

The handling of vectors in Matlab files requires special consideration. Matlab stores vectors as matrices with one dimensions of size 1. VSIPL++ can read matlab vectors as either VSIPL++ vectors or matrices.

The following example shows how to read the v vector from the sample.mat binary file used in the previous examples.

          // Create Matlab_file object for 'sample.mat' file.
  Matlab_file mf("sample.mat");
  Matlab_file::iterator cur = mf.begin();
  Matlab_file::iterator end = mf.end();
  Matlab_view_header* vhdr;

  // Block pointer to hold the vector.  The block will be allocated
  // once it's size is known.
  Dense<1, float>* v_block = NULL;

  // Iterate through views in file.
  while (cur != end)
  {
    vhdr = *cur;

    // Check if view is the one we're looking for.
    //
    // Note: even though 'v' is a vector, it will be 2D because of how
    //       matlab stores vectors.
    if(!strcmp(vhdr->array_name, "v") && vhdr->num_dims == 2)
    {
      // Check for multiple views named "m" in file.
      assert(v_block == NULL);

      // Determine the vector's size:
      length_type size = std::max(vhdr->dims[0], vhdr->dims[1]);

      // Create block and view.
      // At this point we can make the block size match size in the file.
      v_block = new Dense<1, float>(Domain<1>(size));
      Vector<float> tmp(*v_block);

      // Read view from file.
      mf.read_view(tmp, cur);
    }

    ++cur; // Move to next view stored in the file.
  }

  // Check that we found a view named "a" in file.
  assert(v_block != NULL);

  // Create a view to process "m".
  Vector<float> v(*v_block);