MATLAB Answers

per isakson

Design of tool for visual exploration

Asked by per isakson
on 19 Sep 2012


  1. I assume that there is no way to let an assignment, a=qty;, where qty is an instance of a value class, call some user code. (Something like subsref.) Am I correct?
  2. A value class to represent a time series will provide better perfomance and a more robust code than would a handle class. Am I correct?
  3. The design I outline below, does it look sound?


Energy efficient operation of buildings. The building automation system, BAS, provides plenty of time series data: temperatures, power, control signals, etc. Building simulation programs provides similar time series. A building can deliver approximately 1GB per year of data - more in the future.

Some ten year ago I settled on a Matlab structure that contains several hundreds of the time series together with some metadata. Over the years I built a number of visual tools that use my data structure. These tools are used by experts in building operation. The full focus of the user shall be on the behavior of the building. Simple interface and fast response are both important. The tools have been surprisingly well received.

There is a shortcoming that is severe especially when exploring simulation results. Now, in a first step I compile one data structure and in a second step I do the visual exploration. What happens is that when studying a certain behavior in one building I want to compare to the behavior of a different building or simulation and that data are not in the current structure - that irks.

My goal is to make a visual tool, which provides an immense of time series data at the finger tips of the user.

So far

I have concluded based on tests that

  1. it is possible to read data from files on-the-fly and still deliver acceptable response times. A home-brewed system based on fwrite/fread+memmapfile(?), matfile, high level HDF5 and low level NetCDF4 are all possible alternatives. (Soon enough we will have fast solid-state-disks.)
  2. I shall trust Windows' file-cache and Matlabs copy-on-write (/lazy-copy).
  3. I shall try to limit Matlabs memory foot-print. The file cache makes good use of memory.

It is highly possible that several tools simultaneously use a certain time series. In this case it is crucial that there is only one copy of the underlying numerical array in Matlabs memory. Thus, each tool must not retrieve the data from the data file. When all tools have cleared their references to the time series it shall be cleared from the Matlab memory.

Deep under the hood Matlab has information on how variables refer to numerical arrays, but I use plain documented Matlab.

Now I'm experimenting with a little system to study allocation and release of memory. It consists of

  1. SharedQty - A singleton handle class, which keeps a register of QtyX instances in use.
  2. QtyX - A time series value class. Creation of QtyX instancies should only be done by SharedQty
  3. PhysicalMemoryInUse - function
  4. pass_QtyX_as_argument - function

I have ran several scripts like the one below to see how memory is allocated and released. So far it seems to work as expected.

mem(1)  = PhysicalMemoryInUse();
q11     = SharedQty.getQty( 'Qty1001' );        % memory allocated
mem(2)  = PhysicalMemoryInUse();
q21     = SharedQty.getQty( 'Qty1002' );        % memory allocated
mem(3)  = PhysicalMemoryInUse();
mem(4)  = pass_QtyX_as_argument( q11 );
mem(5)  = pass_QtyX_as_argument( q21 );
q12     = copy( q11 );
mem(6)  = PhysicalMemoryInUse();
q22     = copy( q21 );
mem(7)  = PhysicalMemoryInUse();
clear( 'q12' )
mem(8)  = PhysicalMemoryInUse();
clear( 'q22' )
mem(9)  = PhysicalMemoryInUse();
clear( 'q11' )                                  % memory released
mem(10) = PhysicalMemoryInUse();               
clear( 'q21' )                                  % memory released
mem(11) = PhysicalMemoryInUse();


--- listings ---

classdef    ( Sealed ) SharedQty < handle    
%   Singleton pattern
    properties  ( Access = private )
        next_id     = 1;
    methods ( Access = private )        
        function  this = SharedQty()                      
    methods ( Static = true, Access = public ) 
        function    id = unique_id()
            this            = SharedQty.Instance; 
            id              = this.next_id;
            this.next_id    = this.next_id + 1; 
        function    qty = getQty( name )
            this = SharedQty.Instance; 
            if not( isempty( this.QtyBuffer ) )
                [ ism, ixm ] = ismember( name, { this.QtyBuffer.DataName } );
                ism = false;
            if ism
                qty = copy( this.QtyBuffer(ixm).Object );
                qty = QtyX( name );
        function    register( qty )
            this = SharedQty.Instance; 
%           The property, Cleanup, of the instance of QtyX, which is kept in 
%           SharedQty, shall not have a value. The property itself cannot be 
%           removed              
            qty.Cleanup = [];   
            if not( isempty( this.QtyBuffer ) )
                [ ism, ixm ] = ismember( qty.DataName, {this.QtyBuffer.DataName} );
                if ism 
                    this.QtyBuffer(ixm).ID_list ...
                        = [ this.QtyBuffer(ixm).ID_list, qty.ID ];
                    this.QtyBuffer(end+1).ID_list   = qty.ID;
                    this.QtyBuffer(end  ).DataName  = qty.DataName;
                    this.QtyBuffer(end  ).Object    = qty;
                this.QtyBuffer.ID_list   = qty.ID;
                this.QtyBuffer.DataName  = qty.DataName;
                this.QtyBuffer.Object    = qty;
        function    deregister( id, name )
            this = SharedQty.Instance;
            [ ism, loc ] = ismember( name, { this.QtyBuffer.DataName } );
            if ism && sum(loc)==1
                this.QtyBuffer(ism).ID_list ...
                    = setdiff( this.QtyBuffer(ism).ID_list, id );
                if isempty( this.QtyBuffer( ism ).ID_list )
                    this.QtyBuffer( ism ) = [];
    methods ( Static = true, Access = public )                  
        function    this = Instance()
            persistent  instance
            if isempty( instance ) || not( isvalid( instance ) )
                instance = SharedQty;
            this = instance;


    classdef    QtyX  
        properties ( Constant = true )
            Length = 1e8;
            function    this = QtyX( name )
                this.val        = ones( this.Length, 1 ); % mimics file data
                this.ID         = SharedQty.unique_id;
                this.DataName   = name;
                SharedQty.register( this );
                this.Cleanup = onCleanup  ...
                            ( @() SharedQty.deregister( this.ID, this.DataName ) );
            function    qty = copy( this )
                qty         = this;
                qty.ID      = SharedQty.unique_id;
                qty.Cleanup = onCleanup                                         ...
                            ( @() SharedQty.deregister( qty.ID, qty.DataName )  );
            function    qty = set_unique_ID( qty )
                qty.ID      = SharedQty.unique_id;
                qty.Cleanup = onCleanup                                         ...
                            ( @() SharedQty.deregister( qty.ID, qty.DataName )  );


function    mem = PhysicalMemoryInUse()
    pause( 0.5 )
    [ ~, system_view ]  = memory;
    mem = system_view.PhysicalMemory.Total      ...
        - system_view.PhysicalMemory.Available  ;    


function    mem = pass_QtyX_as_argument( qty )
    qty = set_unique_ID( qty );            
    mem = PhysicalMemoryInUse();
    variable_not_used( qty )


Log in to comment.

0 Answers

Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

MATLAB Academy

New to MATLAB?

Learn MATLAB today!