image thumbnail

What's New for Object-Oriented Programming in MATLAB Webinar - Code Examples

by

 

10 Apr 2008 (Updated )

Code examples used in "What's New for Object-Oriented Programming in MATLABĀ®" Webinar

Test for Sensor Array Data Set Object using Value Class

Test for Sensor Array Data Set Object using Value Class

We will now look at defining methods in the class definition file which are the operations that we can carry out with the class.

Contents

Setup

clear
clc
clear import

Packages

I have created a new class definition file and I have stored it a package. Packages, which is a new feature in Release 2008a let you manage names space, allowing you to for example have multiple functions and classes with the same name without adding and removing folders from the MATLAB path.

To put a function or a class in a package you place it in a folder whos name starts with the + symbol. I have placed the class in a package called valueImp meaning value implementation. I will talk about value classes later on. Inside the folder there is one class definition file named sads. Later I'll use packages to let me define other classes with the same name using different implementation techniques.

To use a package, make sure the folder is on your path by adding the parent folder (set you path).

The sads class on its own is not visible. If we try

which sads% ...we can't find it
'sads' not found.

We can access the contents of the package by prefixing with the package name for example:

which valueImp.sads
C:\Documents\My MATLAB Files\Class Examples\R2008a\Webinar\ForMATLABCentral\+valueImp\sads.m  % valueImp.sads constructor

...or we can import the entire valueImp package contents using the import command.

import valueImp.*
which sads
C:\Documents\My MATLAB Files\Class Examples\R2008a\Webinar\ForMATLABCentral\+valueImp\sads.m  % valueImp.sads constructor
import % import shows what we have imported
ans = 

    'valueImp.*'

clear import % removes this

We can import part of the package with

import valueImp.sads
which sads
C:\Documents\My MATLAB Files\Class Examples\R2008a\Webinar\ForMATLABCentral\+valueImp\sads.m  % valueImp.sads constructor

Note that packages can be defined hierarchically to any level.

Classdef structure

Let's take a look at the new class def {Open sads.m). We have grouped the properties into multiple property blocks and specified different attributes which I will describe later. I have added a methods block, with the methods specified as a list of functions inside it.

Different methods

A class can contain many types of methods, each fulfilling a different purpose, each specified differently. We will now look at each of these types and to help us we will create the object with some realistic data.

Load Parameters and view particular scenario

I'm going to load into the workspace some the data items that define a certain scenario. Things like Number of sensors, Number of Samples and the data.

loadparameters

I have a function which displays the scenario showing a number of sensors detecting a number of distant sources. I'll explain the syntax for this later.

sads.showarray(Targets,NumSensors,Spacing)

The true direction of arrival angles we need to estimate are given by:

DirectionsOfArrival
DirectionsOfArrival =

   -10
    20

And here is the data acquired from the sensor array.

Data
Data =

  Columns 1 through 4

   0.0167 + 0.0251i   1.1727 + 0.8783i   1.8563 + 0.7340i   1.2768 + 0.1419i
  -0.0257 - 0.0128i  -1.4665 - 0.0190i  -1.9302 + 0.4946i  -1.1154 + 0.6351i
   0.0283 - 0.0079i   1.2017 - 0.8451i   1.2742 - 1.5353i   0.5330 - 1.1724i
  -0.0141 + 0.0273i  -0.4703 + 1.3905i  -0.1267 + 1.9892i   0.2569 + 1.2580i
  -0.0010 - 0.0301i  -0.4374 - 1.4043i  -1.0678 - 1.6856i  -0.9473 - 0.8647i
   0.0188 + 0.0232i   1.1746 + 0.8772i   1.8561 + 0.7343i   1.2747 + 0.1430i
  -0.0236 - 0.0085i  -1.4671 - 0.0164i  -1.9294 + 0.4957i  -1.1176 + 0.6291i
   0.0298 - 0.0087i   1.1971 - 0.8477i   1.2718 - 1.5389i   0.5292 - 1.1662i
  -0.0192 + 0.0206i  -0.4759 + 1.3895i  -0.1265 + 1.9896i   0.2583 + 1.2551i
  -0.0022 - 0.0262i  -0.4352 - 1.4021i  -1.0700 - 1.6838i  -0.9491 - 0.8679i
   0.0198 + 0.0163i   1.1747 + 0.8794i   1.8542 + 0.7345i   1.2756 + 0.1423i
  -0.0286 - 0.0101i  -1.4704 - 0.0212i  -1.9315 + 0.5005i  -1.1168 + 0.6377i
   0.0286 - 0.0100i   1.1976 - 0.8470i   1.2763 - 1.5350i   0.5338 - 1.1688i
  -0.0196 + 0.0234i  -0.4707 + 1.3918i  -0.1223 + 1.9928i   0.2588 + 1.2556i
  -0.0015 - 0.0296i  -0.4362 - 1.4076i  -1.0703 - 1.6853i  -0.9474 - 0.8627i
   0.0121 + 0.0220i   1.1761 + 0.8775i   1.8561 + 0.7325i   1.2751 + 0.1437i
  -0.0287 - 0.0046i  -1.4717 - 0.0188i  -1.9341 + 0.4961i  -1.1181 + 0.6343i
   0.0271 - 0.0100i   1.2022 - 0.8528i   1.2711 - 1.5398i   0.5328 - 1.1722i
  -0.0167 + 0.0296i  -0.4697 + 1.3910i  -0.1214 + 1.9890i   0.2552 + 1.2586i
   0.0008 - 0.0245i  -0.4389 - 1.4006i  -1.0723 - 1.6830i  -0.9460 - 0.8662i
   0.0163 + 0.0232i   1.1773 + 0.8815i   1.8570 + 0.7326i   1.2766 + 0.1424i
  -0.0275 - 0.0122i  -1.4660 - 0.0168i  -1.9313 + 0.5006i  -1.1175 + 0.6354i
   0.0238 - 0.0088i   1.2028 - 0.8456i   1.2717 - 1.5404i   0.5363 - 1.1685i
  -0.0157 + 0.0217i  -0.4681 + 1.3923i  -0.1246 + 1.9923i   0.2580 + 1.2646i
  -0.0004 - 0.0317i  -0.4338 - 1.4010i  -1.0700 - 1.6887i  -0.9459 - 0.8697i
   0.0197 + 0.0236i   1.1748 + 0.8811i   1.8578 + 0.7358i   1.2733 + 0.1431i
  -0.0272 - 0.0062i  -1.4669 - 0.0188i  -1.9336 + 0.4951i  -1.1119 + 0.6335i
   0.0279 - 0.0111i   1.1996 - 0.8494i   1.2737 - 1.5362i   0.5294 - 1.1682i
  -0.0135 + 0.0228i  -0.4720 + 1.3935i  -0.1280 + 1.9910i   0.2607 + 1.2582i
  -0.0036 - 0.0303i  -0.4366 - 1.4027i  -1.0689 - 1.6833i  -0.9518 - 0.8695i
   0.0153 + 0.0239i   1.1750 + 0.8745i   1.8573 + 0.7337i   1.2733 + 0.1428i
  -0.0279 - 0.0106i  -1.4697 - 0.0193i  -1.9326 + 0.4963i  -1.1178 + 0.6359i
   0.0295 - 0.0072i   1.1980 - 0.8463i   1.2718 - 1.5388i   0.5329 - 1.1693i
  -0.0172 + 0.0229i  -0.4707 + 1.3925i  -0.1248 + 1.9947i   0.2595 + 1.2546i
  -0.0054 - 0.0293i  -0.4352 - 1.4006i  -1.0715 - 1.6843i  -0.9514 - 0.8681i
   0.0172 + 0.0252i   1.1740 + 0.8802i   1.8585 + 0.7346i   1.2791 + 0.1432i
  -0.0284 - 0.0117i  -1.4684 - 0.0218i  -1.9381 + 0.4974i  -1.1198 + 0.6369i
   0.0241 - 0.0100i   1.1983 - 0.8502i   1.2730 - 1.5402i   0.5287 - 1.1693i
  -0.0148 + 0.0250i  -0.4745 + 1.3899i  -0.1250 + 1.9912i   0.2586 + 1.2560i
  -0.0021 - 0.0254i  -0.4342 - 1.4012i  -1.0677 - 1.6861i  -0.9468 - 0.8661i
   0.0145 + 0.0254i   1.1759 + 0.8778i   1.8547 + 0.7345i   1.2758 + 0.1423i
  -0.0268 - 0.0084i  -1.4659 - 0.0184i  -1.9361 + 0.4983i  -1.1191 + 0.6326i
   0.0281 - 0.0108i   1.1967 - 0.8473i   1.2722 - 1.5369i   0.5342 - 1.1710i
  -0.0144 + 0.0257i  -0.4748 + 1.3943i  -0.1284 + 1.9932i   0.2567 + 1.2581i
   0.0008 - 0.0281i  -0.4379 - 1.3979i  -1.0666 - 1.6900i  -0.9473 - 0.8662i
   0.0159 + 0.0228i   1.1766 + 0.8788i   1.8574 + 0.7363i   1.2765 + 0.1449i
  -0.0258 - 0.0038i  -1.4679 - 0.0198i  -1.9328 + 0.4983i  -1.1132 + 0.6355i
   0.0317 - 0.0089i   1.1959 - 0.8511i   1.2709 - 1.5396i   0.5321 - 1.1735i
  -0.0106 + 0.0255i  -0.4671 + 1.3864i  -0.1230 + 1.9948i   0.2576 + 1.2580i
  -0.0021 - 0.0273i  -0.4349 - 1.3971i  -1.0677 - 1.6842i  -0.9506 - 0.8622i
   0.0193 + 0.0255i   1.1805 + 0.8787i   1.8568 + 0.7320i   1.2744 + 0.1487i
  -0.0292 - 0.0112i  -1.4668 - 0.0189i  -1.9303 + 0.5017i  -1.1185 + 0.6324i
   0.0279 - 0.0099i   1.2001 - 0.8474i   1.2727 - 1.5361i   0.5261 - 1.1719i
  -0.0160 + 0.0265i  -0.4724 + 1.3946i  -0.1258 + 1.9924i   0.2594 + 1.2547i
  -0.0011 - 0.0285i  -0.4350 - 1.4031i  -1.0689 - 1.6844i  -0.9500 - 0.8649i
   0.0148 + 0.0244i   1.1773 + 0.8768i   1.8543 + 0.7355i   1.2734 + 0.1478i
  -0.0299 - 0.0086i  -1.4666 - 0.0215i  -1.9308 + 0.4955i  -1.1190 + 0.6326i
   0.0250 - 0.0114i   1.1955 - 0.8461i   1.2746 - 1.5363i   0.5299 - 1.1677i
  -0.0163 + 0.0251i  -0.4704 + 1.3878i  -0.1228 + 1.9922i   0.2548 + 1.2581i
  -0.0009 - 0.0265i  -0.4399 - 1.4021i  -1.0714 - 1.6818i  -0.9453 - 0.8625i
   0.0187 + 0.0209i   1.1786 + 0.8803i   1.8584 + 0.7338i   1.2759 + 0.1437i
  -0.0262 - 0.0095i  -1.4681 - 0.0199i  -1.9387 + 0.4995i  -1.1172 + 0.6328i
   0.0256 - 0.0111i   1.2009 - 0.8497i   1.2708 - 1.5359i   0.5303 - 1.1643i
  -0.0109 + 0.0259i  -0.4717 + 1.3923i  -0.1238 + 1.9895i   0.2536 + 1.2581i

  Columns 5 through 8

  -0.2252 + 0.0348i  -1.4553 + 0.6423i  -1.5305 + 1.2447i  -0.6598 + 0.9179i
...

Creating Sensor Array Data Set Object

Now we will create the data set object, which will involve calling out first method type: the constructor. The optional constructor is called when the object is instantiated. A constructor method often performs data initialization and validation, and can take from none to many arguments. The constructor method is listed as a function with the same name as the class, in the class definition file methods block, shown here.

Constructor

dbtype +valueImp\sads 20:28
20            function obj=sads(Data, Wavelength,SampleRate,Spacing,Name)
21                % SADS Create sensor array data set
22                % Example:
23                %  sads(Data, Wavelength,SampleRate,Spacing,Name)
24    
25                obj.Data=Data;
26                obj.SampleRate=SampleRate;
27                obj.Spacing = Spacing;
28                obj.Name=Name;

We create the object, passing the key data items to the constructor as arguments with:

s=sads(Data, Wavelength,SampleRate,Spacing,Name);

Here is the object s now with all properties defined. We can also look at it in the workspace browser.

s
s = 

valueImp.sads
package: valueImp

properties:
          Data: [64x16 double]
    SampleRate: 3.3333e+007
       Spacing: 1.2500
          Name: 'Sensor Array Amplitudes'
             c: 300000000
    NumSensors: 16
    NumSamples: 64


Regular Application Specific Methods

We have added several methods to implement application-specific operations to be performed on the data set. These include the main doa method, which calls other methods, such as magfft which calculates the fft which we will look at (open magfft). Most methods take the object as an input argument (often named, obj or this) and access the object properties by referencing this variable (for example, obj.NumSamples), as in the magfft method.

dbtype +valueImp\sads 31:37
31            function [mags, fflip]=magfft(obj,zeroPadTo)
32                % MAGFFT Calculate the magnitude square of the FFT of the
33                % sensor array sample data, zeropadding by zeroPadTo elements
34                % Example:
35                %  result=magfft(s,128);
36    
37                mag=zeros(obj.NumSamples,zeroPadTo); % Preallocate store of magnitudes

Although it requires additional syntax, having to reference properties via the object variable can help differentiate them from local function variables, like mag. You don't need a naming convention such as m_ like in C++ to denote properties.

Calling Methods

Methods are called just like functions, with the object(s) passed in as one of the arguments. You can use functional or dot notation. We will call the method that calculates the magnitude squared of the fft, passing in the additional required arguments.

result=magfft(s,128); % Functional notation
result=s.magfft(128); % Dot notation, object implicitly passed in as first argument

Calling More Operations

Next we will execute the plot magnitude FFT operation to see what the results vector looks like.

magfftplot(s,128); % Here we see two peaks.

Calculating Directions of Arrival

Finally, we will call the operation (method) that performs the main task of estimating the DOA of the sources.

angles=doa(s)
angles =

   -9.7080   19.4712

Overwriting Existing MATLAB Operations with Overloading

You can use overloading to redefine existing MATLAB functions to work on your object by providing a function with that name in your list of methods. You can also overload operators and even indexing by specifying methods with special names (e.g. plus for addition, subsref for indexing). We have included an overloaded plot method (open plot method), providing a function to visualize the data set that is familiar to many MATLAB users.

plot(s);

This customized plot method represents the information in the most appropriate way for this data set, annotating it with all available information. This plot method is executed only on objects for which it has been defined, a much more robust approach than manipulating the order of directories in the path to control which of the multiple functions with the same name are called.

Finding Available Operations (Methods)

The methods command can be used to find available operations for an object.

methods(s)
Methods for class valueImp.sads:

doa         magfftplot  sads        
magfft      plot        steer       

Static Methods:

showarray   

Getting Help on Individual Operations (Methods)

You can get help on a particular operation with the help, specifying the complete class name first.

help valueImp.sads.plot
  PLOT Plot the sensor array sample data set
  Example:
   plot(ds);

Controlling Access to Data Property Attributes

Let's now look at properties again. Classes give you great control over property access. They are all public by default but you can prohibit modification of a property, hide a property, or cause it to be calculated dynamically. You do this with property attributes.

Properties with different attributes must be placed in separate property blocks. We have three blocks here. First of all we still have some public properties in this block.

You prohibit modification of a property by setting the Constant attribute. In our example, we will set the speed of light property c to be constant. Because constant properties do not change, they can be accessed simply by referencing the class name.

sads.c % Constant
ans =

   300000000

You can make properties visible only to the methods operating on it by setting the Access and Access attribute to private, such as with the Wavelength property in this example. As a result, it cannot be accessed by a user of the object. The following code will error (which we will catch).

try
    s.Wavelength % Hidden with Access=private attribute
catch ME
    disp(ME.message)
end
Getting the 'Wavelength' property of the 'valueImp.sads' class is not allowed.

You can freely change the names or characteristics of private properties without affecting users of the object. This "black box" approach to defining a piece of software, known as encapsulation, prevents the user of the object from becoming dependant on an implementation detail or characteristic that could change and break their code.

You can specify that a property is calculated only when asked for by setting its attribute to Dependent. In our example we set the NumSensors and NumSamples properties to be dependent. You then specify a get method that is automatically called when the property is accessed.

Accessing Properties with Get and Set Methods

dbtype +valueImp\sads 50:53
s.NumSensors      % Dynamically calculated
50            function NumSensors=get.NumSensors(obj)
51                % Get NumSensors property
52                NumSensors=size(obj.Data,2);
53            end


ans =

    16

Set methods can be used to validate properties, such as making sure they are within a certain range, before assigning them.

Specifying Data Set/Class Operations (Static Methods)

The last type of method I'd like to show you is static methods. Static methods are defined for the class as a whole, not for an instance of the class. Static methods are often used to associate related or utility functions with a class. In the sads class definition we have specified a static method showarray, which I have already called if you remember that plots the array geometry and actual source angles. We have created another methods block and specified the Static attribute (open methods block).

sads.showarray(Targets,NumSensors,Spacing)

Functions outside

One other feature I'd like to point out is functions outside of the classdef statement. These can be accessed by the methods but they themselves cannot access object properties.

Separate Methods

Note that you do not have to put the code for all the methods into the classdef file. You can put the in separate function files. If you create a directory whose name begins with an @ symbol plus the name of the class name on the path, inside it, you can list the methods separately (see +valueSeparateMethods\@sads).

You still need a classdef file. It contains the properties and events if there are any. In the case of methods it needs to contain the constructor and the get and set methods. For the other functions that are specified as separate methods, you just list the function name with the input and output arguments.

If you had a function local to the class after the classdef statement, you need to either make it local to the method using it, if it is just one as is the case here. {e.g. doa}. If it is used by multiple methods you need to make a static method and mark it as private.

Clean up

clear import

Contact us