3

I have two arrays which contain times. The first is the state of a device indicating when power was turned on and the second array is time stamps of the actual command issued to the device. See plot below: enter image description here

The vertical dashed lines indicate power on commands and the blue line represents device state (1= on 0 = off).

What I want to do is create a matrix matching up commands to device responses. The trouble is that they are not 1 for 1. There are redundant commands and extra power cycles (from manual operations ect.). Ideally I would like to pair an un-commanded state change to a NaN in the command column and similarly any redundant commands or commands that don't result in a state change to a NaN in the state column. See sample data and desired output below:

indicatesOn = [1 2 3 4 5];
commandIssue = [1.9 2.8 2.9 4.8 4.9 5.1]

matchedOutput =

       NaN    1.0000
    1.9000    2.0000
    2.8000       NaN
    2.9000    3.0000
       NaN    4.0000
    4.8000       NaN
    4.9000    5.0000
    5.1000       NaN

So basically the Command times are in Column 1 and Power on is in Column 2. A NaN in the Command column would signify that there was not a preceding command to the change in state (manual operation of device). A NaN in the State/power-on column would signify that the device did not respond to that particular command (either already on or multiple commands were issued).

I started trying to sort this out and got into a mess of for loops and lots of if/else logic and thought there had to be a better way.

Any help is appreciated!

EDIT:

Aero Engy
  • 3,588
  • 1
  • 16
  • 27
  • I may be over-complicating it, but this is akin to sequence alignment in biology, and I believe an approach based on Dynamic Programming might be ideal. If you have the bioinformatics toolbox, you can use the function `samplealign` to do it. – foglerit Feb 15 '12 at 15:31
  • You may look at a similar (but sure not the same) question: http://stackoverflow.com/questions/2142826/mapping-2-vectors-help-to-vectorize – yuk Feb 15 '12 at 15:39
  • @jonnat I do not have access to that toolbox ... and I think I had a slight brain aneurysm when I read the documentation for `samplealign`. – Aero Engy Feb 15 '12 at 15:51
  • You'd better post your code as an answer and remove from the question. – yuk Feb 15 '12 at 18:17
  • @yuk I wasn't really sure if answering your own question was completely copacetic since there is a warning popup when answering your own question. However, I moved it as you suggested. – Aero Engy Feb 15 '12 at 18:47
  • Answering your own question is perfectly fine. You even can accept your own question. Other people may upvote your answer and you will get reputation points. And best of all the question will not remain unanswered. – yuk Feb 15 '12 at 19:09

1 Answers1

1

I took a break, ran a couple miles, then took another crack at it and this is the best I have come up with so far.

indicatesOn = [1 2 3 4 5];
cmdIssue = [1.9 2.8 2.9 4.8 4.9 5.1];

cmdIndex = arrayfun(@(x) find(cmdIssue < x,1,'last'),indicatesOn,'uniformoutput',false);
outState = indicatesOn(:);
outCmd = nan(size(outState));
usedCmds = false(size(cmdIssue(:)));
for k =1:numel(cmdIndex)
    if ~isempty(cmdIndex{k})        
        outCmd(k,1) = cmdIssue(cmdIndex{k});
        usedCmds(cmdIndex{k}) = true;
    end
end

%Fix duplicate Commands (replace with NaN)
outCmd(diff(outCmd)==0) = NaN; 
remCmds = cmdIssue(~usedCmds);
outCmd = [outCmd;remCmds(:)];  %Append remaining unprocessed Cmds
outState = [outState;nan(numel(remCmds),1)]; %Add NaNs to state.

%Sort the output by the min time stamp row-wise
matchedOutput = [outCmd outState];
[temp sortI] = sort(min(matchedOutput,[],2));
matchedOutput = matchedOutput(sortI,:)

Resulting in:

matchedOutput =

       NaN    1.0000
    1.9000    2.0000
    2.8000       NaN
    2.9000    4.0000
       NaN    3.0000
    4.8000       NaN
    4.9000    5.0000
    5.1000       NaN

If anyone sees any room for improvement or logic holes let me know.

Aero Engy
  • 3,588
  • 1
  • 16
  • 27