bas
bas

Reputation: 209

Matlab events and listeners: propagate information out of the Event call

I have an object that incorporates an event which is created in my program(specifically, a session based ni daq with a 'DataAvailable' event which fires every time a set number of samples is acquired.) This event will be fired at random times during the course of running my program that will do other stuff independent of recording. When fired, it will collect and save the data chunk in a file.

My issue is that everytime the Event is triggered, i need to increase a counter (i name it "chunk") in my original program. This is critical as a number of features in my program depend on my being able to measure the number of chunks accurately.

QUESTION: how can i propagate the fact that an event has been triggered into my main program?

For people who process (pseudo)code better:

setupStuff();
endLoop = false;
while ~endLoop
  if ~recording
    session  = createDAQSessionObject(params);
    chunkNum = 0;
    session.addListener('DataAvailable',@(src,event)saveChunk(src,event,chunkNum));
    session.startBackGround()
    recording  = true;
  end
  endLoop = doOtherStuff();
  pause(0.1);
end

function saveChunk(src,event,numChunk)
  filename = sprintf('chunk%d.mat',numChunk);
  times = event.TimeStamps;
  data = event.Data;
  save(filename,'times','data');
  % but now the next time around we need to get in numChunks+1 (but we never will because we have no way of knowing that the event was called...
end

Thanks

-bas

Upvotes: 1

Views: 1272

Answers (1)

Yvon
Yvon

Reputation: 2983

Using global or persistent does the job in this minimal example -

  1. Define a class to be the event source.

    classdef bar < handle
        events
            sayhello
        end
    end
    
  2. Build a function that uses a persistent variable num. num is visible only to function foo, but it is "persistent" between calls to foo. It remains in foo's workspace until clear all is excecuted, or Matlab quits.

    function foo(~,~)
    persistent num
    if isempty(num)
        num = 1;
    else
        num = num+1;
    end
    fprintf('hi %d\n', num);
    end
    

    .... and call it from main script

    bigjob = bar;
    addlistener(bigjob, 'sayhello', @foo);
    
    for ii = 1:10
        notify(bigjob, 'sayhello')
    end
    

    Output:

    hi 1
    hi 2
    hi 3
    hi 4
    hi 5
    hi 6
    hi 7
    hi 8
    hi 9
    hi 10
    >> 
    
  3. Build another function that uses a global variable num. num is kept in base workspace, visible to all functions as well as the main script, and is alive until clear global num is called or Matlab quits.

    function foo(~,~)
    global num
    num = num+1;
    fprintf('hi %d\n', num);
    end
    

    .... and change the script to declare and initialize the global num

    global num
    num = 0;
    bigjob = bar;
    addlistener(bigjob, 'sayhello', @foo);
    
    for ii = 1:10
        notify(bigjob, 'sayhello')
    end
    

    Output:

    hi 1
    hi 2
    hi 3
    hi 4
    hi 5
    hi 6
    hi 7
    hi 8
    hi 9
    hi 10
    >> 
    

Efficiency concerns

Using global or persistent is costly. I changed my code to ii = 50000, and muted the fprintf, to perform a benchmark.

According to Profiler, using global takes ~10% of total running time; by "using global" I mean declaring global num in function foo.

.... while using persistent takes ~25% of total running time (it adds up to the total, so running persistent is slower than global); by "using persistent" I mean these lines

persistent num
if isempty(num)
else
end

Upvotes: 3

Related Questions